分享给大家Spring中两种动态代理(笔记留存,收藏备用)
动态代理
相较于静态代理,动态代理更为灵活,在程序运行期间产生代理类(动态生成不固定) 通过使用放射的机制
可以理解为全能中介的作用吧.代理行为均可以增强目标对象的行为
和cglib的区别在于: 目标对象是否有接口的实现 若有就选择jdk动态代理
首先 自定义一个代理对象接口 我这里写的是ProxyInter 将目标对象实现这个接口
我将得到代理对象提取成一个类中的方法
public class JdkProxy {
//目标对象
private Object target;
public JdkProxy(Object target) {
this.target = target;
}
/**
*
/**
* ClassLoader loader 类加载器
* Class[] interfaces 目标对象的接口数组
*InvocationHandler是由代理实例的调用处理程序实现的接口。
* 每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理 *程序的invoke方法
* @return
*/
public Object getProxy() {
ClassLoader loader = this.getClass().getClassLoader();
Class[] interfaces = target.getClass().getInterfaces();
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(target, args);
return result;
}
};
;
Object proxy = Proxy.newProxyInstance(loader, interfaces, invocationHandler);
return proxy;
}
}
这样做 主程序中只需要new出目标对象 将目标对象放入得到代理对象后 代理对象再执行其方法即可
public static void main(String[] args) {
//目标对象
Zhangsan zs = new Zhangsan();
//得到代理对象类
JdkProxy jdkProxy = new JdkProxy(zs);
//得到代理对象
ProxyInter proxy = (ProxyInter) jdkProxy.getProxy();
//通过代理对象调用目标对象的方法
proxy.method();
}
增强方式就是在 invocationHandler类中的invoke方法上下进行增强即可
2. Cglib动态代理
与jdk动态代理不同,他不需要实现接口类
运行过程中只会生成目标对象的子类Enhancer enhancer 运用继承的方式实现动态代理
首先 定义一个目标对象
public class Person {
public void eat(){
System.out.println("吃饭...");
}
}
想jdk代理一样 我们将方法提取到一个类中
public class CglibProxy {
//目标对象
private Object target;
public CglibProxy(Object target) {
this.target = target;
}
//得到代理对象
public Object getProxy() {
//得到目标类的代理类
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(target.getClass());
MethodInterceptor methodInterceptor = new MethodInterceptor() {
/**
* 当代理对象调用任意方法时 都会将调用信息传递到形参中
* @param obj 代理对象
* @param method 目标对象的方法
* @param args 目标对象方法列表
* @param proxy 子类中目标方法的引用
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("饭前洗手...");
Object result = method.invoke(target, args);
System.out.println("饭后洗碗...");
return result;
}
};
//设置Callback回调
enhancer.setCallback(methodInterceptor);
//生成类
return enhancer.create();
}
}
主程序我们执行
public class Starts {
public static void main(String[] args) {
//目标对象
Person person = new Person();
CglibProxy cglibProxy = new CglibProxy(person);
Person proxy = (Person) cglibProxy.getProxy();
proxy.eat();
}
}
那么cglib动态代理完成了
3.两者的区别
在我看来,但凡目标对象有实现的接口就会选择jdk动态代理的方式,因为效率更高
没有接口只能借助第三方的cglib了(使用之前一定要配置pom哦)
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>