概括:
spring aop的实现原理:
动态代理
cglib代理
动态代理
代理模式:
静态代理
动态代理
(Spring如果发现被代理的类有接口的话,就用动态代理,否则用cglib)
动态代理 反射
JAVA的动态代理
代理模式
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
按照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。
主要用来做方法的增强,让你可以在不修改源码的情况下,增强一些方法,在方法执行前后做任何你想做的事情(甚至根本不去执行这个方法),因为在InvocationHandler的invoke方法中,你可以直接获取正在调用方法对应的Method对象,具体应用的话,比如可以添加调用日志,做事务控制等。
在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。
每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。
Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法。
- 创建被代理的类以及接口。
- 创建一个实现接口InvocationHandler的类,他必须实现invoke方法
- 通过Proxy的静态方法newProxyInstance(ClassLoader loader,Class【】interfaces,InvocationHandler handler)创建一个代理
- 通过代理调用方法。
建接口:
建实现类:
注意没用动态代理前,要想实现事务管理,需要在每个方法前后加上事务代码:
使用动态代理技术对这个实现类进行代理,来增强实现类里面的方法,例如把事务的代码插入到放到方法中。
import java.lang.reflect.Proxy;
public class UserServiceProxyFactory implements InvocationHandler {
public UserService getUserServiceProxy() {
//要执行的方法所在的对象
private UserService us;
public UserServiceProxyFactory(UserService us) {
super();
this.us = us;
}
//生成动态代理
UserService usProxy = (UserService)Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(),
UserServiceImpl.class.getInterfaces(),
this)
/*public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
loader:类加载器,随便给一个
interfaces:被代理对象的实现的接口
h:这次代理要增强的内容,此处传一个InvocationHandler接口*/
//返回
return usProxy;
}
@Override
public Object invoke() {
Object invoke(Object proxy, Method method, Object[] args) {
System.out.println("模拟打开事务"); //增强代码
Object invoke = method.invoke(us, args); //原有方法的调用,业务执行代码
System.out.println("模拟提交事务"); //增强代码
return invoke;
}
/*Object invoke(Object proxy, Method method, Object[] args) throws Throwable
proxy:当前的代理对象
method:当前调用的方法
args:当前方法执行时的参数*/
}
}