zoukankan      html  css  js  c++  java
  • AOP之JDK动态代理和CGLib动态代理

    一、JDK动态代理

     JDK内置的Proxy动态代理可以在运行时动态生成字节码,而没必要针对每个类编写代理类。中间主要使用到了一个接口InvocationHandler与Proxy.newProxyInstance静态方法,参数说明如下:

     使用内置的Proxy实现动态代理有一个问题:被代理的类必须实现接口,未实现接口则没办法完成动态代理。

    1.编写接口类

    public interface IUserDao {
        public String add();
        public String edit();
    }
    

    2.编写实现类

    public class UserDaoImpl implements IUserDao {
        public String add() {
            System.out.println("add");
            return "add";
        }
    
        public String edit() {
            System.out.println("edit");
            return "edit";
        }
    }
    

    3.编写测试类

        //JDK动态代理
        @Test
        public void  DTTest(){
           final IUserDao dao = new UserDaoImpl();
            IUserDao proxy =(IUserDao)Proxy.newProxyInstance(dao.getClass().getClassLoader(), dao.getClass().getInterfaces(), new InvocationHandler() {
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("事物已经开启!");
                    method.invoke(dao,args);
                    return null;
                }
            });
            //代理对象add edit
            proxy.add();
            proxy.edit();
        } 

    4.测试结果

    二、CGLIB动态代理

    CGLIB(Code Generation Library)是一个开源项目,是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口,通俗说cglib可以在运行时动态生成字节码。不需要有接口。

    原理是:cglib继承被代理的类,重写方法,织入通知,动态生成字节码并运行 

    cglib封装了asm,可以在运行期动态生成新的class。

    1.编写业务类

    public class UserService {
        //核心业务方法
        public void  deleter(){
            System.out.println("delete ok");
        }
    }
    

    2.编写测试类

        //CGLIB动态代理
        @Test
        public void testCGlib() {
            //对方法进行增强,不破坏原有方法的业务
            //1.创建一个目标对象
            final UserService service = new UserService();
            //2.Enhancer对象
            Enhancer enhancer = new Enhancer();
            //3.在内存中构建业务类的子类    //设置父类
            enhancer.setSuperclass(service.getClass());
    
     /*  1、第一种方法
         enhancer.setCallback(new MethodInterceptor() {
                *//*
                * 第一个参数:Object为由CGLib动态生成的代理类实例
                * 第二个参数:Method为上文中实体类所调用的被代理的方法引用
                * 第三个参数:Object[]为参数值列表
                * 第四个参数:MethodProxy为生成的代理类对方法的代理引用
                * *//*
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    System.out.println("事物已经开启");
                    methodProxy.invoke(service,objects);
                    return null;
                }
            });*/
    
    
            //4.调度setCallback     第二种方法
            enhancer.setCallback(new org.springframework.cglib.proxy.InvocationHandler() {
                public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                    System.out.println("事物已经开启");
                    method.invoke(service,objects);
                    return null;
                }
            });
            //enhancer对象create方法创建出一个代理
            UserService proxy = (UserService)enhancer.create();
            //执行代理对象的deleter方法
            proxy.deleter();
        }
    

    3.测试结果

      

      

      

     

  • 相关阅读:
    Thinking Clearly about Performance
    国家统计局2018-10-30统计的最新的省市区
    Java 返回字符串中第一个不重复字符的下标 下标从0开始
    国际象棋的游戏规则
    Python语言之requests库
    VBS 自动发消息给对方
    Windows
    上海合计共有16个区一个县
    @RequestMapping中的注解
    Linux 中 /proc/kcore为啥如此之大
  • 原文地址:https://www.cnblogs.com/cn-930621/p/7657952.html
Copyright © 2011-2022 走看看