动态代理技术

1.装饰者模式的缺点:
很麻烦 做到了无侵入式增强,缺憾 代码工作量多 会导致类结构爆炸。
2.动态代理技术优化
保留 无侵入增强的特色
去除 写大量代码 写大量类
3 动态代理技术 在java领域两种实现方式:
1.jdk自带方法
好处不需要引入别的jar包 用起来简单 缺点 如果增强一个对象 被增强 必须有个接口
2.第三方jar包
asm 难度第一 性能最好
cglib 难度第二 性能第二
javassist 难度最低 性能跟第二个差不多
缺点引入第三方jar包 优点 不需要接口也可以增强
4.jdk动态代理
在java.lang.reflect 包 有一个类 Proxy 有一个方法 帮助实现
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) ;
使用这个方法 可以直接帮你产出一个已经被增强过的对象
三个参数:
ClassLoader:类加载器 随便一个类加载器(给一个除去特殊 引导类加载,和扩展类加载 使用自己引入第三方自己的类 得到那个类加载器)
interfaces:接口数组 传入原本对象实现所有接口数组
InvocationHandler:执行处理类对象(难点);
实现它InvocationHandler接口
Object invoke(Object proxy, Method method, Object[] args)
proxy:代表的是 即将返回的增强对象
method:代表的是增强对象调用方法的时候的方法本身
args:代表的是增强对象调用方法传入实参本身
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

public class Demo01 {
    public static void main(String[] args) {
        //目的增强逻辑
        QQ qq=new QQ();
        //换动态代理 返回一个增强的对象
        Car zq = (Car) Proxy.newProxyInstance(
                Demo01.class.getClassLoader(),
                qq.getClass().getInterfaces(),
                new MyInvocationHandler(qq)
        );
        //zq.run();
        //zq.stop();
        //zq.driver("小明");
        //int i = zq.oilTank();
        //System.out.println(i);
        zq.didi().didi().didi();
    }
    private static class MyInvocationHandler implements InvocationHandler{
        private Car car;
        public MyInvocationHandler(Car car) {
            this.car = car;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //System.out.println(proxy);
            //System.out.println(method.getName());
            if ("run".equals(method.getName())){
                long start = System.currentTimeMillis();
                //  平常调用方法 对象.方法
                //  方法.invoke(对象)
                method.invoke(car);
                long end = System.currentTimeMillis();
                System.out.println("百公里加速用时"+(end-start));
            }else if("driver".equals(method.getName())) {
                System.out.println(Arrays.toString(args));
                method.invoke(car,args[0]+"的媳妇儿")
            }else if("oilTank".equals(method.getName())) {
                Integer invoke = (Integer) method.invoke(car, args);
                return invoke+100;
            }else if("didi".equals(method.getName())) {
                System.out.print("增强对象在调用:");
                method.invoke(car);
                return proxy;
            }else {
                //调用原来的方法
                method.invoke(car);
            }
            return null;
        }
    }

注意:a.didi().didi().didi()为链式编程(递归)
在这里插入图片描述
在这里插入图片描述

5.javassist 实现动态代理

无接口也可实现
首先导入jar包
在这里插入图片描述
材料准备
在这里插入图片描述
本来的功能,接下开始增强
在这里插入图片描述

public class Demo {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        User user = new User();
        user.setUsername("小明");
        //偷偷改掉你这个方法
        ProxyFactory proxyFactory=new ProxyFactory();
        //User.class父类
        proxyFactory.setSuperclass(User.class);
        proxyFactory.setHandler(new MethodHandler() {
            @Override
            public Object invoke(Object o, Method method, Method method1, Object[] objects) throws Throwable {
                System.out.println(method.getName());
                System.out.println("自己补充逻辑");
                return "我偷偷把你的返回值改了";
            }
        });
        Class<?> aClass = proxyFactory.createClass();
        User o = (User) aClass.newInstance();
        String username = o.getUsername();
        System.out.println(username);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值