静态代理与动态代理

静态代理

  • 代理模式

    (1)代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理。

(2)静态代理由 业务实现类、业务代理类 两部分组成。业务实现类 负责实现主要的业务方法,业务代理类负责对调用的业务方法作拦截、过滤、预处理,主要是在方法中首先进行预处理动作,然后调用业务实现类的方法

  • 例子

        /**
     * 定义一个账户接口
     * @author Administrator
     */
    public interface Count {
        // 查询账户
        public void queryCount();  

        // 修改账户
        public void updateCount();  

    }
    /**
 * 委托类(包含业务逻辑)
 *
 * @author Administrator
 *
 */
public class CountImpl implements Count {  

    @Override
    public void queryCount() {
        System.out.println("查看账户...");  

    }  

    @Override
    public void updateCount() {
        System.out.println("修改账户...");  

    }
}
    public class CountProxy implements Count {
    private CountImpl countImpl;  //组合一个业务实现类对象来进行真正的业务方法的调用

    /**
     * 覆盖默认构造器
     *
     * @param countImpl
     */
    public CountProxy(CountImpl countImpl) {
        this.countImpl = countImpl;
    }  

    @Override
    public void queryCount() {
        System.out.println("查询账户的预处理——————");
        // 调用真正的查询账户方法
        countImpl.queryCount();
        System.out.println("查询账户之后————————");
    }  

    @Override
    public void updateCount() {
        System.out.println("修改账户之前的预处理——————");
        // 调用真正的修改账户操作
        countImpl.updateCount();
        System.out.println("修改账户之后——————————");
    }
}
  • 静态代理

    静态代理的缺点很明显:一个代理类只能对一个业务接口的实现类进行包装,如果有多个业务接口的话就要定义很多实现类和代理类才行。而且,如果代理类对业务方法的预处理、调用后操作都是一样的(比如:调用前输出提示、调用后自动关闭连接),则多个代理类就会有很多重复代码。这时我们可以定义这样一个代理类,它能代理所有实现类的方法调用:根据传进来的业务实现类和方法名进行具体调用。——那就是动态代理。


动态代理

  • JDK动态代理

    JDK动态代理设计到java.lang.relect包中的两个类:Proxy和InvocationHandler,InvocationHandler可以通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态将横切逻辑与业务逻辑编织到一起。Proxy利用InvocationHandler动态创建某一符合该接口的实例,生成目标类的代理对象。

    public class Monitor {

    public static void begin(){
        System.out.println("before");
    }

    public static void end(){
        System.out.println("after");
    }
}
    public interface CouponService {

    void getCoupon();
}
    public class CouponServiceImpl implements CouponService {

    public void getCoupon() {

        //Monitor.begin();
        try {
            System.out.println("业务代码");
        } catch (Exception e) {
            throw new RuntimeException();
        }
        //Monitor.end();
    }
}
    public class PerformanceHandler implements InvocationHandler {

    //被代理对象
    private Object target;

    public PerformanceHandler(Object target) {
        this.target = target;
    }

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

        Monitor.begin();
        Object object = method.invoke(target, args);
        Monitor.end();
        return object;
    }
}
    public class Client {

    public static void main(String[] args) {

        //被代理对象
        CouponService target = new CouponServiceImpl();

        //让PerformanceHandler将监视横切逻辑编织到CouponService中
        PerformanceHandler performanceHandler = new PerformanceHandler(target);

        //通过Proxy的newProxyInstace()方法,为编织了业务逻辑与监控逻辑的handler创建一个符合CouponService接口的代理实现
        CouponService proxy = (CouponService) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),performanceHandler);

        proxy.getCoupon();
    }
}
  • Cglib 实现动态代理
    JDK创建代理只能为接口创建代理,实际开发中我们很难保证每个类都有其对应的接口,对于没有通过接口定义业务方法的类,JDK已经没法对其进行代理,这就出现了Cglib,通过字节码技术,为一个类创建子类,在子类中采用方法拦截的技术拦截所有父类方法的调用并织入横切逻辑。
    public class CglibProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz) {
        //设置需要创建子类的类
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        //通过字节码技术动态创建子类实例
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before");
        //通过代理类调用父类中的方法
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("after");
        return result;
    }
}
    public class Client {

    public static void main(String[] args) {
        CglibProxy proxy = new CglibProxy();

        //通过冬天生成子类的方式创建代理类
        CouponServiceImpl couponService = (CouponServiceImpl) proxy.getProxy(CouponServiceImpl.class);

        couponService.getCoupon();
    }
}
  • 总结

    Cglib所创建的动态代理,性能要比jdk创建的动态代理高。但对用Cglib创建代理的时间,JDK动态代理显然要快很多。对于无需单例的代理对象或实例池可以使用CGLib来创建代理(无需频繁创建),反之使用JDK动态代理。

Spring AOP JDK动态代理与CGLib动态代理区别的更多相关文章

  1. 【转载】Spring AOP详解 、 JDK动态代理、CGLib动态代理

    Spring AOP详解 . JDK动态代理.CGLib动态代理  原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspec ...

  2. 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。

    基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...

  3. Spring -- <tx:annotation-driven>注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别。

    借鉴:http://jinnianshilongnian.iteye.com/blog/1508018 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional ...

  4. Java之代理(jdk静态代理,jdk动态代理,cglib动态代理,aop,aspectj)

    一.概念 代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道.如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法. ...

  5. Spring <tx:annotation-driven>注解 JDK动态代理和CGLIB动态代理 区别。

    基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...

  6. 浅谈Spring中JDK动态代理与CGLIB动态代理

    前言Spring是Java程序员基本不可能绕开的一个框架,它的核心思想是IOC(控制反转)和AOP(面向切面编程).在Spring中这两个核心思想都是基于设计模式实现的,IOC思想的实现基于工厂模式, ...

  7. Spring 静态代理+JDK动态代理和CGLIB动态代理

    代理分为两种:静态代理 动态代理 静态代理:本质上会在硬盘上创建一个真正的物理类 动态代理:本质上是在内存中构建出一个类. 如果多个类需要进行方法增强,静态代理则需要创建多个物理类,占用磁盘空间.而动 ...

  8. jdk动态代理与cglib动态代理例子

    1.JAVA的动态代理特征:特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象 ...

  9. java的静态代理、jdk动态代理和cglib动态代理

    Java的代理就是客户端不再直接和委托类打交道,而是通过一个中间层来访问,这个中间层就是代理.使用代理有两个好处,一是可以隐藏委托类的实现:二是可以实现客户与委托类之间的解耦,在不修改委托类代码的情况 ...

  10. 从静态代理,jdk动态代理到cglib动态代理-一文搞懂代理模式

    从代理模式到动态代理 代理模式是一种理论上非常简单,但是各种地方的实现往往却非常复杂.本文将从代理模式的基本概念出发,探讨代理模式在java领域的应用与实现.读完本文你将get到以下几点: 为什么需要 ...

随机推荐

  1. 1. 全文搜索框架 Haystack

    1.什么是Haystack Haystack是django的开源全文搜索框架(全文检索不同于特定字段的模糊查询,使用全文检索的效率更高 ),该框架支持Solr,Elasticsearch,Whoosh ...

  2. MyBatis从入门到精通(1):MyBatis入门

    作为一个自学Java的自动化专业211大学本科生,在学习和实践过程中"趟了不少雷",所以有志于建立一个适合同样有热情学习Java技术的参考"排雷手册". 最近在 ...

  3. PJzhang:python基础入门的7个疗程-five

    猫宁!!! 参考链接:易灵微课-21天轻松掌握零基础python入门必修课 https://www.liaoxuefeng.com/wiki/1016959663602400 第十三天:代码组织 类是 ...

  4. Android解决RecyclerView中的item显示不全方案

    最近的项目中实现订单确定页面.需要使用ScrollView嵌套RecyclerView,当RecyclerView中的item数量比较多时,就会出现item只显示一部分数据,并没有将用户勾选的商品数量 ...

  5. WPF依赖属性的正确学习方法

    前言 我在学习WPF的早期,对依赖属性理解一直都非常的不到位,其恶果就是,我每次在写依赖属性的时候,需要翻过去的代码来复制黏贴. 相信很多朋友有着和我相同的经历,所以这篇文章希望能帮助到那些刚刚开始学 ...

  6. Golang高效实践之泛谈篇

    前言 我博客之前的Golang高效实践系列博客中已经系统的介绍了Golang的一些高效实践建议,例如: <Golang高效实践之interface.reflection.json实践>&l ...

  7. kudu集群高可用搭建

    首先咱得有KUDU安装包 这里就不提供直接下载地址了(因为有5G,我 的服务器网卡只有4M,你们下的很慢) 这里使用的是CDH版本 官方下载地址http://archive.cloudera.com/ ...

  8. java中dao层和service层的区别是什么

    dao层中已经有操作数据库的方法了,为什么还要service层去封装?有什么好处? tanghui12321 | 浏览 131990 次  我有更好的答案  推荐于2017-10-06 18:44:5 ...

  9. Drools规则引擎-如果判断某个对象中的集合是否包含指定的值

    规则引擎集合相关处理 在实际生产过程中,有很多关于集合的处理场景,比如一个Fact对象中包含有一个集合,而需要判断该集合是否包含某个值.而Drools规则引擎也提供了多种处理方式,比如通过from.c ...

  10. 【iOS】CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable

    CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SH ...