动态代理理解

动态代理

代理是一种模式,提供了对目标对象的间接访问方式,即通过代理对象访问目标对象,如此便于在目标实现的基础上增加额外的功能操作,以满足自身的业务需求
在这里插入图片描述
即,就是给调用者不直接找到目标对象,而是通过找到中间商,中间商再给调用者找目标对象

JDK提供了java.lang.relect.InvocationHandler接口和java.lang.reflect.Proxy类这两个类为了实现动态代理

动态代理图解
在这里插入图片描述
在这里插入图片描述

    @Test
    public void test2() throws IllegalAccessException, InstantiationException {
        //通过接口得到代理类Class对象
        Class<?> proxyClass = Proxy.getProxyClass(BussinessInterface.class.getClassLoader(), BussinessInterface.class);
        //通过反射创建代理类对象
        Object proxy = proxyClass.newInstance();
    }

但是在运行这段代码的时候,会抛出异常
在这里插入图片描述
这是因为newInstance()方法底层是调用的无参构造,但是Proxy类的无参构造是私有的
在这里插入图片描述
我们无法使用私有化的无参构造,只能使用下面的有参构造

 @Test
    public void test2() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //通过接口得到代理类Class对象
        Class<?> proxyClass = Proxy.getProxyClass(BussinessInterface.class.getClassLoader(), BussinessInterface.class);
        //通过反射创建代理类对象
        Constructor<?> constructor = proxyClass.getDeclaredConstructor(InvocationHandler.class);
        BussinessInterface proxy = (BussinessInterface) constructor.newInstance(new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return null;
            }
        });
          //调用方法
        System.out.println(proxy.execute());
    }

得到的结果是null
是因为每次调用代理对象的方法都会调用invoke(),且invoke()的返回值就是代理方法的返回值
动态代理的大致设计思路
在这里插入图片描述
所以应该设法在invoke()方法得到目标对象,并调用目标对象的同名方法

 private static Object getProxy(final Object target) throws Exception {
        //参数1:随便找个类加载器给它, 参数2:目标对象实现的接口,让代理对象实现相同接口
        Class proxyClazz = Proxy.getProxyClass(target.getClass().getClassLoader(), target.getClass().getInterfaces());
        Constructor constructor = proxyClazz.getConstructor(InvocationHandler.class);
        Object proxy = constructor.newInstance(new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println(method.getName() + "方法开始执行...");
                Object result = method.invoke(target, args);
                System.out.println(result);
                System.out.println(method.getName() + "方法执行结束...");
                return result;
            }
        });
        return proxy;
    }
   @Test
    public void test2() throws Exception {
        BussinessInterface proxy = (BussinessInterface)getProxy(new Bussiness());
        //调用方法
        proxy.execute();
    }

在这里插入图片描述
Java实现动态代理的方式
1、JDK动态代理:java.lang.reflect 包中的 Proxy 类和 InvocationHandler 接口提供了生成动态代理类的能力。
2、Cglib动态代理:Cglib (Code Generation Library )是一个第三方代码生成类库,运行时在内存中动态生成一个子类对象从而实现对目标对象功能的扩展。

JDK原生动态代理是Java原生支持的,不需要外部依赖,但是它只能基于接口进行代理(需要动态代理的对象必须实现与某个接口)

CGLIB通过继承的方式进行代理,要导入cglib第三方库,使用的类是Enhancer的create静态方法创建,要求被代理类不能是最终类,即不能用final修饰,如String类。

使用cglib实现动态代理:

 <dependency>
     <groupId>cglib</groupId>
     <artifactId>cglib</artifactId>
     <version>3.3.0</version>
</dependency>
   @Test
    public void test3(){
        // 创建一个被代理对象,这里要求必须是final
        final Bussiness target = new Bussiness();
        Bussiness proxy =(Bussiness) Enhancer.create(target.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object returnValue = null;
                System.out.println(method.getName() + "方法开始执行...");
                returnValue = method.invoke(target, objects);
                System.out.println(method.getName() + "方法执行结束...");
                return returnValue;
            }
        });
        proxy.execute();
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值