关于springAOP动态代理技术和JDK动态代理技术的疑问

I_Have_A_Dream- 发布于 2017/12/21 17:03
阅读 136
收藏 2

JDK的动态代理是面向于接口的,而Spring的AOP理论上也是面向于接口的。但是我好像记得之前官网(是不是官网给忘了,要不就是某个社区论坛上面)说是注解式的aop(比如说是事务管理)倾向于在具体的实现类上注解。这不是有矛盾的么。求大神解答一下。

另外附一个代码问题:

public class DynaProxyDone implements InvocationHandler {
	
	//切面对象
	private Object proxy;
	//业务代理对象
	private Object object;
	
	//获取代理类的实例
	public Object getInstance(Object o,Object p){
		this.proxy = p;
		this.object = o;
		return Proxy.newProxyInstance(this.object.getClass().getClassLoader(), this.object.getClass().getInterfaces(),this);
	}
	/**
	 * 切面方法,用于AOP的切面编程
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// TODO Auto-generated method stub
		Object result = null;
		//获取切面对象的类类型
		 Class<?> c = this.proxy.getClass();
		 //反射获取start方法
		 Method start = c.getDeclaredMethod("start",null);
		 //调用start方法
		 start.invoke(this.proxy,null);
		 //处理业务对象逻辑
		 method.invoke(this.object, args);
		 //反射获取end方法
		 Method end = c.getDeclaredMethod("end",null);
		 //调用end方法
		 end.invoke(this.proxy,null);
		return result;
	}

}
public class DoneImpl implements Done {

	@Override
	public void dosomething(String str) {
		System.out.println(str+" has already doing....");
	}
}

public class Main {

	public static void main(String[] args) {
		Done done = (Done) new DynaProxyDone().getInstance(new DoneImpl1(),new LoggerImpl1());
		//这个没怎么理解,为什么会在这里出现切面逻辑处理。
		done.dosomething("test");
	}
}
加载中
0
l
lizhi.zero

动态代理就是在运行环境生成Proxy$Object.class而已。打开生成的classes 看看多出了哪些class。

再学习一下java的类加载机制,有的时候生成的class只在内存中,所以也是会生成一个类似的proxy¥object.class。

最后最后总结一下,jvm不认识class也不认识java只认识字节码,说白了动态代理就是在运行时生成了一段字节码,然后运行这段字节码。这样以来,在生成字节码的时候,你可以动态的在字节码中添加想要的功能,当然你添加的功能都是字节码形式存在。所以无论的jdk还是spring aop(其实应该是cglib)帮你做了这些而已。

I
I_Have_A_Dream-
我这个理解对不对?另外你回答说JVM不认识class,JVM不是将class文件转化成内存的么。。。
I
I_Have_A_Dream-
通过反编译可以看出来该二进制文件中出现了业务接口中的方法,而该方法只有一个方法invoke(),它执行的就是你的动态代理类所实现的invoke(),所以执行done.dosomething(xxx)的时候它只会执行二进制class文件中的invoke()方法。可以理解为此时已经将业务方法与切面方法绑在一起了。
I
I_Have_A_Dream-
谢谢这个哥们的回答,我通过网上的资料和源码得出的答案看下是否和你理解的一样: Proxy.newProxyInstance()它生成的不是真正意义上的实现类,而是一个由Proxy.newProxyInstance中getProxyClass生成的一个二进制的class文件(com.sun.proxy.$Proxy0)
0
l
lizhi.zero
//这个没怎么理解,为什么会在这里出现切面逻辑处理。

 

总得告诉程序你要生成字节码了吧。告诉程序你要增强那个class的功能吧。要不然你以为

Done done =

怎么产生的?

 

0
Simonton
Simonton

AOP是用于解决特定业务的手段。接口是用于定义规范,正真的业务是在实现类的里去实现的。所以AOP使用在具体的实现类上用于满足业务,没毛病啊。。。

感觉没get到你的问题核心。

 

I
I_Have_A_Dream-
嗯,可能是我理解的JDK代理有问题吧。 JDK代理虽然是通过接口来生成二进制字节码的,但是这个二进制class文件中实现的时候(调用invoke())是要传入具体你需要增强的方法的实现类。所以本质上还是在实现类上做切面处理。
返回顶部
顶部