动态代理

绪论

一、什么是动态代理

是使用反射和字节码的技术,在运行期创建指定接口或类的子类,以及其实例对象的技术,通过这个技术可以无侵入的为代码进行增强(代码无侵入的增强

举例:卖车,工厂把车生产出来,经销商4s店买车,工厂就是被代理的类,4s就是代理类,4s店对车进行送膜,送脚垫,送保养就是做增强。

二、jdk动态代理

1、jdk实现动态代理主要是俩个类,Proxy、InvocationHandler,

  • Proxy: 是所有动态代理的父类,它提供了一个静态方法来创建动态代理的class对象和实例
  • InvocationHandler: 每个动态代理实例都有一个关联的InvocationHandler,在代理实例上调用方法是,方法调用将被转发到InvocationHandler的invoke方法

代码层:

2、代理类实现InvocationHandler接口

public class DynamicHandler implements InvocationHandler {

    private Object target;

    public DynamicHandler(Object target) {
        this.target=target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法之前
        System.out.println("方法之前执行...."+method.getName()+" :传递的参数..."+ Arrays.toString(args));
        //被增强的方法执行
        Object res = method.invoke(target, args);
        //方法之后
        System.out.println("方法之后执行...."+target);
        return res;
    }
}

3、服务层

public interface DynamicService {

    Integer add(Integer a, Integer b);

    Integer sub(Integer a, Integer b);
}

public class DynamicServiceImpl implements DynamicService {

    @Override
    public Integer add(Integer a, Integer b) {
        int c=a+b;
        System.out.println("答案:"+c);
        return c;
    }

    @Override
    public Integer sub(Integer a, Integer b) {
        int c=a-b;
        System.out.println("答案:"+c);
        return c;
    }

}

4、实现jdk代理

Proxy.newProxyInstance代理类:
    public void testFun1(){
        Class[] classes={DynamicService.class};
     //代理类
        DynamicService proxyInstance =(DynamicService) Proxy.newProxyInstance(this.getClass().getClassLoader(), classes, new DynamicHandler(new DynamicServiceImpl()));
        Integer result = proxyInstance.add(1, 2);
        System.out.println("result:"+result);
    }

JDK方法之前执行....add :JDK传递的参数...[1, 2]
答案:3
JDK方法之后执行....com.mvc.testdemo2.dynamic.DynamicServiceImpl@7cbd213e
result:3

 

 

三、cglib动态代理

1、CGLIB的实现也有两个重要的成员组成,EnhancerMethodInterceptor

  • Enhancer 来指定要代理的目标对象,实际处理代理逻辑的对象,最终通过调用create()方法得到代理对象、对这个对象所有的非final方法的调用都会转发给MethodInterceptor
  • MethodInterceptor 动态代理对象的方法调用都会转发到intercept方法进行增强

2、创建MethodInterceptor实现类

public class CGLIBDynamicHander implements MethodInterceptor {

    private Object target;

    public CGLIBDynamicHander(Object target) {
        this.target=target;
    }

    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        //方法之前
        System.out.println("CGLIB方法之前执行...."+method.getName()+" :CGLIB传递的参数..."+ Arrays.toString(args));
        //被增强的方法执行
        Object res = method.invoke(target, args);
        //方法之后
        System.out.println("CGLIB方法之后执行...."+target);
        return res;
    }
}

3、实现cglib代理

 @Test
    public void testFun2(){
        Enhancer enhancer=new Enhancer();

        DynamicServiceImpl dynamicService = new DynamicServiceImpl();

        enhancer.setSuperclass(dynamicService.getClass());
        enhancer.setCallback(new CGLIBDynamicHander(dynamicService));

        DynamicServiceImpl dynamicServiceProxt =(DynamicServiceImpl) enhancer.create();

        Integer result = dynamicServiceProxt.add(1, 2);

        System.out.println("result:"+result);
    }

CGLIB方法之前执行....add :CGLIB传递的参数...[1, 2]
答案:3
CGLIB方法之后执行....com.mvc.testdemo2.dynamic.DynamicServiceImpl@174d20a
result:3

四、总结

1、JDK原声动态代理时java原声支持的、不需要任何外部依赖、但是它只能基于接口进行代理(因为它已经继承了proxy了,java不支持多继承)

2、CGLIB通过继承的方式进行代理、无论目标对象没有没实现接口都可以代理,但是无法处理final的情况(final修饰的方法不能被覆写)

posted @ 2022-09-29 17:55  清华大咖  阅读(281)  评论(0编辑  收藏  举报