JDK动态代理与CGLIB字节码增强

时间:2021-10-21 13:30:10

1.1.1   JDK动态代理

l  JDK动态代理 对“装饰者”设计模式简化。使用前提:必须有接口

1.目标类:接口 + 实现类

2.切面类:用于存通知 MyAspect

3.工厂类:编写工厂生成代理

4.测试

 

1.1.1.1        目标类

public interface UserService {

  

   public void addUser();

   public void updateUser();

   public void deleteUser();

 

}

 

1.1.1.2        切面类

public class MyAspect {

  

   public void before(){

      System.out.println("鸡首");

   }

  

   public void after(){

      System.out.println("牛后");

   }

 

}

 

 

1.1.1.3        工厂

public class MyBeanFactory {

  

   public static UserService createService(){

      //1 目标类

      final UserService userService = new UserServiceImpl();

      //2切面类

      final MyAspect myAspect = new MyAspect();

      /* 3 代理类:将目标类(切入点)和切面类(通知)结合 --> 切面

       * Proxy.newProxyInstance

       *    参数1loader ,类加载器,动态代理类运行时创建,任何类都需要类加载器将其加载到内存。

       *       一般情况:当前类.class.getClassLoader();

       *              目标类实例.getClass().get...

       *    参数2Class[] interfaces 代理类需要实现的所有接口

       *        方式1:目标类实例.getClass().getInterfaces()  ;注意:只能获得自己接口,不能获得父元素接口

       *        方式2new Class[]{UserService.class}  

       *        例如:jdbc驱动  --> DriverManager  获得接口 Connection

       *    参数3InvocationHandler  处理类,接口,必须进行实现类,一般采用匿名内部

       *        提供 invoke 方法,代理类的每一个方法执行时,都将调用一次invoke

       *           参数31Object proxy :代理对象

       *           参数32Method method : 代理对象当前执行的方法的描述对象(反射)

       *              执行方法名:method.getName()

       *              执行方法:method.invoke(对象,实际参数)

       *           参数33Object[] args :方法实际参数

       *

       */

      UserService proxService = (UserService)Proxy.newProxyInstance(

                         MyBeanFactory.class.getClassLoader(),

                         userService.getClass().getInterfaces(),

                         new InvocationHandler() {

                           

                            @Override

                            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                              

                               //前执行

                               myAspect.before();

                              

                               //执行目标类的方法

                               Object obj = method.invoke(userService, args);

                              

                               //后执行

                               myAspect.after();

                              

                               return obj;

                            }

                         });

     

      return proxService;

   }

 

}

 

 

1.1.1.4        测试

@Test

   publicvoid demo01(){

      UserService userService = MyBeanFactory.createService();

      userService.addUser();

      userService.updateUser();

      userService.deleteUser();

   }

 

 

1.1.2   CGLIB字节码增强

l  没有接口,只有实现类。

l  采用字节码增强框架 cglib,在运行时 创建目标类的子类,从而对目标类进行增强。

l  导入jar包:

       自己导包(了解):

              核心:hibernate-distribution-3.6.10.Final\lib\bytecode\cglib\cglib-2.2.jar

              依赖:struts-2.3.15.3\apps\struts2-blank\WEB-INF\lib\asm-3.3.jar

       spring-core..jar已经整合以上两个内容

             JDK动态代理与CGLIB字节码增强

      JDK动态代理与CGLIB字节码增强

JDK动态代理与CGLIB字节码增强

 

 

 

1.1.2.1        工厂类

public class MyBeanFactory {

  

   public static UserServiceImpl createService(){

      //1 目标类

      final UserServiceImpl userService = new UserServiceImpl();

      //2切面类

      final MyAspect myAspect = new MyAspect();

      // 3.代理类,采用cglib,底层创建目标类的子类

      //3.1 核心类

      Enhancer enhancer = new Enhancer();

      //3.2 确定父类

      enhancer.setSuperclass(userService.getClass());

      /* 3.3 设置回调函数 , MethodInterceptor接口等效 jdk InvocationHandler接口

       * intercept() 等效 jdk  invoke()

       *    参数1、参数2、参数3:以invoke一样

       *    参数4methodProxy 方法的代理

       *   

       *

       */

      enhancer.setCallback(new MethodInterceptor(){

 

         @Override

         public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

           

            //

            myAspect.before();

           

            //执行目标类的方法

            Object obj = method.invoke(userService, args);

            // * 执行代理类的父类,执行目标类(目标类和代理类父子关系)

            methodProxy.invokeSuper(proxy, args);

           

            //

            myAspect.after();

           

            return obj;

         }

      });

      //3.4 创建代理

      UserServiceImpl proxService = (UserServiceImpl) enhancer.create();

     

      return proxService;

   }

 

}