黑马程序员技术交流社区

标题: 【成都校区】代理模式之Cglib代理 [打印本页]

作者: 逍遥来了    时间: 2019-1-10 12:47
标题: 【成都校区】代理模式之Cglib代理
即便是动态代理,也需要被代理对象实现接口或具有超类,从网上了解到一个叫Cglib代理方式可以更加灵活。
Cglib代理(子类代理)
    * 如果目标对象没有没有实现任何接口,则可使用此方式。它在内存中构建一个子类对象从而实现对目标功能的扩展。
        1. Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口.它广泛的被许多AOP的框架使用,例如Spring AOP和synaop,为他们提供方法的interception(拦截)。
        2. Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类.不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉.
    * 实现方法
        1. 需要引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,所以直接引入`pring-core-3.2.5.jar`即可.
        2. 引入功能包后,就可以在内存中动态构建子类
        3. 代理的类不能为final,否则报错
        4. 目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法
    * 示例  
        目标对象类:UserDao.java
        ```java
            //没有实现任何接口
            public class UserDao {
                public void save() {
                    System.out.println("----已经保存数据!----");
                }
            }
        ```  
        Cglib代理工厂:ProxyFactory.java
        ```java
            /**
             * Cglib子类代理工厂
             * 对UserDao在内存中动态构建一个子类对象
             */
            public class ProxyFactory implements MethodInterceptor{
                //维护目标对象
                private Object target;
   
                public ProxyFactory(Object target) {
                    this.target = target;
                }
   
                //给目标对象创建一个代理对象
                public Object getProxyInstance(){
                    //1.工具类
                    Enhancer en = new Enhancer();
                    //2.设置父类
                    en.setSuperclass(target.getClass());
                    //3.设置回调函数
                    en.setCallback(this);
                    //4.创建子类(代理对象)
                    return en.create();
                }
   
                @Override
                public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                    System.out.println("开始事务...");
                    //执行目标对象的方法
                    Object returnValue = method.invoke(target, args);      
                    System.out.println("提交事务...");
                    return returnValue;
                }
            }
            ```  
            测试类
            ```java
            public class App {
                @Test
                public void test(){
                    //目标对象
                    UserDao target = new UserDao();
                    //代理对象
                    UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance();        
                    //执行代理对象的方法
                    proxy.save();
                }
            }
            ```




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2