zoukankan      html  css  js  c++  java
  • 代理模式之Cglib代理

    Cglib代理,也叫做子类代理。在内存中构建一个子类对象从而实现对目标对象功能的扩展。

    JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用CGLIB实现。

      CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。

     CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。

    Cglib子类代理:

             1) 需要引入cglib – jar文件, 但是spring的核心包中已经包括了cglib功能,所以直接引入spring-core-3.2.5.jar即可。

             2)引入功能包后,就可以在内存中动态构建子类

             3)代理的类不能为final, 否则报错。

             4) 目标对象的方法如果为final/static, 那么就不会被拦截,即不会执行目标对象额外的业务方法。

    在Spring的AOP编程中,

             如果加入容器的目标对象有实现接口,用JDK代理;

             如果目标对象没有实现接口,用Cglib代理;

    package loaderman.c_cglib;
    
    import java.lang.reflect.Method;
    
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    /**
     * 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;
        }
    
    }
    package loaderman.c_cglib;
    
    /**
     * 目标对象
     *
     */
    public class UserDao {
    
        public void save() {
            System.out.println("-----已经保存数据!!!------");
        }
    
    }
    package loaderman.c_cglib;
    
    public class App {
    
        public static void main(String[] args) {
            // 目标对象
            UserDao target = new UserDao();
            // class loaderman.c_cglib.UserDao
            System.out.println(target.getClass());
    
            // 代理对象
            UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance();
            // UserDao子类:class loaderman.c_cglib.UserDao$$EnhancerByCGLIB$$25d4aeab
            System.out.println(proxy.getClass());
    
            // 执行代理对象的方法
            proxy.save();
        }
    }

  • 相关阅读:
    arcgis建立拓扑分析(检验矢量图)
    矢量图面层和线层相交得到相交后的线层文件(gis相交)
    关于处理注册表权限无法修改的问题(无法打开主键或注册表项unknown)
    my.cnf配置文件
    keepalived联动mysql
    安装客户端连接软件(zabbix_agentd-filebeat-flume)
    zabbix短信配置说明
    zabbix监控工具添加网络设备Ping
    新买了硬盘,让Linux系统识别硬盘nfs---->改成xfs
    vnc软件使用
  • 原文地址:https://www.cnblogs.com/loaderman/p/10042768.html
Copyright © 2011-2022 走看看