JDK动态代理和CGLIB代理
程序员文章站
2022-06-18 11:10:21
...
JDK代理
参考
https://www.cnblogs.com/MOBIN/p/5597215.html
通过实现接口实现
通过动态代理,给普通的对象生成代理对象,对其中的方法进行前置和后置的处理
例如spring的事务
使用动态代理的五大步骤
1.通过实现InvocationHandler接口来自定义自己的InvocationHandler;
2.通过Proxy.getProxyClass获得动态代理类
3.通过反射机制获得代理类的构造方法,方法签名为getConstructor(InvocationHandler.class)
4.通过构造函数获得代理对象并将自定义的InvocationHandler实例对象传为参数传入
5.通过代理对象调用目标方法
//接口
public interface MyBuyInterface {
void buy(String goods);
}
//实现这这个接口,也就是后面需要代理的对象
public class MyBuyClass implements MyBuyInterface {
@Override
public void buy(String goods) {
System.out.println("我买了 " + goods);
}
}
//实现自己的InvocationHandler
//实现InvocationHander接口
public class MyInvocationHandler implements InvocationHandler{
//需要被代理的对象
private Object target;
public MyInvocationHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//前置处理
System.out.println(new Date());
//这里是实际调用实际的方法
Object res = method.invoke(target, args);
//后置处理
System.out.println("买完了");
return res;
}
}
//进行实际的调用
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//方法一
//获取代理类
Class<?> proxyClass = Proxy.getProxyClass(MyBuyInterface.class.getClassLoader(), MyBuyInterface.class);
//获取代理类的构造方法,传入InvocationHandler接口
Constructor<?> constructor = proxyClass.getConstructor(InvocationHandler.class);
//通过构造方法创建代理对象,传入自定义invocationHandler
MyBuyInterface obj = (MyBuyInterface) constructor.newInstance(new MyInvocationHandler(new MyBuyClass()));
//调用方法,此时会调用自定义invocationHandler的invoke方法
obj.buy("苹果");
//方法二
//上面的几步可以通过下面这个方法合并为一步
MyBuyInterface oobbjj = (MyBuyInterface) Proxy.newProxyInstance(MyBuyInterface.class.getClassLoader(), new Class[] {MyBuyInterface.class}, new MyInvocationHandler(new MyBuyClass()));
oobbjj.buy("梨子");
}
运行结果
Tue Aug 28 12:15:37 CST 2018
我买了 苹果
买完了
Tue Aug 28 12:15:37 CST 2018
我买了 梨子
买完了
CGLIB代理
CGLIB会让生成的代理类继承被代理类,并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。在CGLIB底层,其实是借助了ASM这个非常强大的Java字节码生成框架。
//自定义方法拦截器,实现MethodInterceptor 接口
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable {
System.out.println(new Date());
Object res = proxy.invokeSuper(obj, arg);
System.out.println("买完了");
return res;
}
}
//进行调用
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(MyBuyClass.class);
//设置方法拦截器
enhancer.setCallback(new MyMethodInterceptor());
//生成代理类
MyBuyClass myBuyClass = (MyBuyClass)enhancer.create();
myBuyClass.buy("梨子");
}
//运行结果
Tue Aug 28 13:37:38 CST 2018
我买了 梨子
买完了
代理类将委托类作为自己的父类并为其中的非final委托方法创建两个方法,一个是与委托方法签名相同的方法,它在方法中会通过super调用委托方法;另一个是代理类独有的方法。在代理方法中,它会判断是否存在实现了MethodInterceptor接口的对象,若存在则将调用intercept方法对委托方法进行代理