美文网首页
使用cglib实现动态代理技术

使用cglib实现动态代理技术

作者: capo | 来源:发表于2017-08-19 12:22 被阅读44次

    Spring AOP(面向切面编程)使用了两种技术实现,一种是JDK自带的动态代理,另外一种是使用cglib字节码技术动态生成代理类。Spring是如何选择的了:

    • 如果目标对象实现了接口,默认情况先回选择使用JDK代理技术实现AOP,但是也可以强制使用cglib实现动态代理
    • 如果目标对象没有实现接口,则会采用cglib技术实现AOP

    cglib创建某个动态代理类的模式是:

    • 查找目标类上所有非 final 的public类型的方法,将这些方法的定义转换成字节码
    • 将组成的字节码转换成相应的代理的class对象
    • 代理类实现MethodInterceptor接口,用来处理代理类上所有方法的请求(中介)

    下面是代码:

    定义一个通用接口,里面定义一些要拦截的方法

    package com.minglangx.cglib;
    
    /**
    * 
    
      * @ClassName: UserService
    
      * @Description: 通用接口类
    
      * @author minglangx
    
      * @date 2017年8月19日 下午12:02:34
    
      *
    
    
      
    */
    public interface UserService {
    
       String getName(String name);
       Integer getAge(int age);
       
    }
    

    定义一个目标对象,实现这个通用接口

    package com.minglangx.cglib;
    /**
     * 
    
      * @ClassName: UserServiceImpl
    
      * @Description: 目标对象
    
      * @author minglangx
    
      * @date 2017年8月19日 下午12:02:52
    
      *
    
    
      
     */
    public class UserServiceImpl implements UserService {
    
        @Override
        public String getName(String name) {
            System.out.println("===getName===");
            return name;
        }
    
        @Override
        public Integer getAge(int age) {
            System.out.println("====getAge=====");
            return age;
        }
    
    }
    

    核心代理类,实现MethodInterceptor接口

    package com.minglangx.cglib;
    
    import java.lang.reflect.Method;
    import java.util.Arrays;
    
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    /**
     * 
     * 
     * @ClassName: CglibDemo
     * 
     * @Description: 代理类使用 Cglib实现动态代理
     * 
     * @author minglangx
     * 
     * @date 2017年8月18日 下午12:33:51
     *
     * 
     * 
     * 
     * 
     */
    class CglibDemo implements MethodInterceptor {
    
        
        /**
         * Object obj 被代理的对象
         * Method method 被拦截的方法
         * Object[] objs 方法的参数
         * MethodProxy methodProxy  cglib中的代理对象
         * 
         * 
         */
        @Override
        public Object intercept(Object obj, Method method, Object[] objs, MethodProxy methodProxy) throws Throwable {
            System.out.println("======before " + methodProxy.getSuperName() + "======");
            System.out.println("被拦截的方法名称-----" + method.getName());
            System.out.println("被拦截的方法参数-----" + Arrays.asList(objs));
            //invokeSuper(obj,objs) 第一个参数是被代理对象,第二个参数是参数集合
            Object objNew = methodProxy.invokeSuper(obj, objs);
            System.out.println("+++++before " + methodProxy.getSuperName() + "=====");
            return objNew;
        }
        
        
        
        
        
    
    }
    

    测试类

    • 使用 Enhancer().setSuperclass(目标对象); 设置要代理的对象
    • 使用 Enchancer.setCallback(目标对象); 将要代理对象的所有方法都转发到intercept()方法上进行拦截
    • 使用Enchancer.create();获取被代理的对象
    package com.minglangx.cglib;
    
    import net.sf.cglib.proxy.Enhancer;
    import com.minglangx.cglib.UserService;
    import com.minglangx.cglib.UserServiceImpl;
    
    public class MainDemo {
    
        public static void main(String[] args) {
    
            CglibDemo cglibDemo = new CglibDemo();
            //cglib中的加强器,用来创建动态代理
            Enhancer enhancer = new Enhancer();
                   //设置要动态创建的类
            enhancer.setSuperclass(UserServiceImpl.class);
            /*
             * 设置回调.这里相当于是对于代理类上所有方法的回调,都会调用CallBack,
             * 而Callback需要执行intercept()方法进行拦截
             */
            enhancer.setCallback(cglibDemo);
            
            //得到实际对象的接口类型,调用其方法
            UserService o =(UserService) enhancer.create();
            o.getName("zhangs");
            o.getAge(25);
            
            
            
            
        }
    
    }
    

    输出结果: 我们看到在被代理对象调用方法之前成功实现了方法的拦截

    image.png

    相关文章

      网友评论

          本文标题:使用cglib实现动态代理技术

          本文链接:https://www.haomeiwen.com/subject/ksltdxtx.html