代码先锋网 代码片段及技术文章聚合

spring中的常见设计模式

技术标签: 架构之路  java  spring

代理模式

  • 代理模式常用的地方:

      AOP的功能完全继承到了Spring事务管理、日志和其他各种特性的上下文中。
      Authentication权限认证
      Logging日志
      Transctions Manager事务
      Lazy Loading懒加载
      Context Process上下文处理
      Error Handler错误跟踪(异常捕获机制)
      Cache缓存处理
    
  • 分为静态代理、动态代理

      JDK 动态代理:
      CGLib 动态代理:
      cglib.jar (全称 Code Generation Library 代码生成库)
      asm.jar(全称 assembly,装配)
    
  • 代理的特点:

      1、执行者、被代理人
      2、对于被代理人来说,这件事情是一定要做的,但是我自己又不想做或者没有时间做,找代理。
      3、需要获取到被代理的人个人资料。
    
  • 穷举法:

      租房中介:中介和你
      火车票黄牛:黄牛和你
      媒人:媒婆和你
      明星经纪人:经纪人和明星
      刘德华要开演唱会(长沙)、准备工作和善后工作
      快递:
    
  • 总结:做了一件什么事情呢?

字节码重组

可以做一件什么事情? 
	可以在每一个方法调用之前加一些代码,在方法调用之后再加一些代码
AOP:事务代理(声明式事务,哪个方法需要加事务,哪个方法不需要加事务)
  • 日志监听

      service 方法
      开启一个事务(open)
      事务的执行(是由我们自己的代码完成的)
      监听到是否有异常,可能需要根据异常的类型来决定这个事务是否要回滚还是继续提交
      (commit/rollback)
      事务要关闭(close)
    
  • 代理的原理

      1、拿到被代理对象的引用,然后获取它的接口;
      2、JDK代理重新生成一个类,同时实现我们给的代理对象所实现的接口。
      3、把被代理对象的引用也拿到了
      4、重新动态生成一个class字节码
      5、然后编译
    
  • JDK代理与cglib代理

      JDK代理:实现自InvocationHandler接口,实现代理
      cglib代理:实现自MyMethodInterceptor接口,实现代理
      
      JDK的动态动力是通过接口来进行强制转换的
      生成以后的代理对象,可以强制转换为接口
      
      CGLib的动态代理是通过生成一个被代理对象的子类,然后重写父类的方法,
      生成以后的对象,可以强制转换为被代理对象(也就是用自己写的类),
      子类引用赋值给父类。
      
      cglib new出来以后的对象,是被代理对象的子类(继承课我们自己写的那个类),
      OOP,在new子类之前,实际上默认先调用了我们super()方法的,
      new了子类的同时,必须先new出来父类,这就相当于是间接的持有了我们父类的引用。
      子类重写了父类的所有的方法,
      我们改变子类对象的某些属性,是可以间接的操作父类的属性的。
    
  • Cglib和jdk动态代理的区别?

      1、Jdk动态代理:利用拦截器(必须实现InvocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
      2、Cglib动态代理:利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成子类来处理。
    
  • 什么时候用cglib什么时候用jdk动态代理?

      1、目标对象生成了接口 默认用JDK动态代理
      2、如果目标对象使用了接口,可以强制使用cglib
      3、如果目标对象没有实现接口,必须采用cglib库,Spring会自动在JDK动态代理和cglib之间转换
    
  • JDK动态代理和cglib字节码生成的区别?

      1、JDK动态代理只能对实现了接口的类生成代理,而不能针对类
      2、Cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,并覆盖其中方法的增强,但是因为采用的是继承,所以该类或方法最好不要生成final,对于final类或方法,是无法继承的
    
  • Spring如何选择是用JDK还是cglib?

      1、当bean实现接口时,会用JDK代理模式
      2、当bean没有实现接口,用cglib实现
      3、可以强制使用cglib(在spring配置中加入<aop:aspectj-autoproxy proxyt-target-class=”true”/>)
    
  • cglib举例:

1、引入依赖:

<dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.3.0</version>
</dependency>

2、创建一个被代理人的对象:

public class ZhangSanFindLove {

    public void findLove(){
        System.out.println("牛郎织女七夕来相会...");
    }
}

3、创建一个代理人对象:

public class MyMethodInterceptor implements MethodInterceptor {

    /**
     * @param clazz 文件的字节码文件
     * @return 具体的对象
     */
    public  Object getInstance(Class clazz){
        //通过Enhancer对象进行代理操作
        Enhancer enhancer = new Enhancer();
        //设置父类
        enhancer.setSuperclass(clazz);
        //设置回调
        enhancer.setCallback(this);
        //调用Enhancer对象的创建并返回
        return enhancer.create();
    }
    /**
     * @param className 文件的全路径名称
     * @return 具体的对象
     */
    public  Object getInstance(String className){
        //通过Enhancer对象进行代理操作
        Enhancer enhancer = new Enhancer();
        //设置父类
        try {
            enhancer.setSuperclass(Class.forName(className));
        } catch (ClassNotFoundException e) {

        }
        //设置回调
        enhancer.setCallback(this);
        //调用Enhancer对象的创建并返回
        return enhancer.create();
    }

    public Object intercept(Object o, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
        System.out.println("我是媒婆,你得给我找个异性");
        System.out.println("--------------------------");
        /**
         * 不能使用invoke,invoke是指向自己
         * Cglib是给指定的类添加一个子类对象,所以应该指向父类节点
         * 为父类自动塑造出一个子类
         */
        proxy.invokeSuper(o , objects);
        System.out.println("--------------------------");
        System.out.println("合适,就步入婚礼的殿堂");
        return null;
    }
}
  • 测试类:

      public class FindLoveTest {
      
          public static void main(String[] args) {
              ZhangSanFindLove instance = (ZhangSanFindLove)new MyMethodInterceptor().getInstance("gupaoedu.vip.agent.cglib.ZhangSanFindLove");
              ZhangSanFindLove instance1 = (ZhangSanFindLove)new MyMethodInterceptor().getInstance(ZhangSanFindLove.class);
              instance.findLove();
              instance1.findLove();
          }
      }
    
版权声明:本文为weixin_42779560原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_42779560/article/details/108254660

智能推荐

常见的设计模式

1、设计模式七大原则 单一职责原则 一个类只负责一项功能,在类或者方法(方法及其简单时)级别遵守单一职责原则 接口隔离原则 客户端不应该依赖他不需要的接口,即一个类对另一个类的依赖应该建立在最小接口之上 依赖倒置原则 高层模块不应该依赖底层模块,二者都应该依赖其抽象 抽象不应该依赖细节,细节应该依赖抽象 依赖倒置的中心思想是面向接口编程 设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为...

常见的设计模式

常见的设计模式分为三类:创建型、结构型、行为型 单例模式 简单工厂模式 简单工厂模式是a类想调用b类,不直接new b类,直接new出来耦合性太高,b的实例而是通过b类的实例工厂获得。如果b类的实例工厂也是由另一个工厂获得的,这种叫抽象工厂。 代理模式 就是实现相同逻辑的一个类,作为代理,代理模式使用场景分为两个方面:延迟加载功能、增强原目标对象的功能。增强原目标对象的功能可使用jdk的动态代理实...

常见的设计模式

常见的设计模式 创建型模式 单例(Singleton) Intent Implementation Ⅰ 懒汉式-线程不安全 Ⅱ 饿汉式-线程安全 Ⅲ 懒汉式-线程安全 Ⅳ 双重校验锁-线程安全 简单工厂(Simple Factory) Intent Class Diagram 工厂方法(Factory Method) Intent Class Diagram 抽象工厂(Abstract Facto...

常见的设计模式

https://www.runoob.com/design-pattern/design-pattern-tutorial.html 设计模式: 1.简单工厂模式:(静态方法) 2048小游戏,计算器 2.装饰者模式:Thread thread=new Thread(()->System.out.println()); 3.代理模式: 把real类当作proxy类的属性,进一步封装,两个类都...

常见的设计模式

目录   1.工厂模式(侧重于对象的创建) 1.1.简单工厂模式 1.2.工厂方法模式(几种实现就几个小工厂) 1.3.抽象工厂模式 1.3.1.针对多个接口合并成抽象工厂 1.3.2.然后实现各个接口的具体工厂 1.3.3.创建一个工厂创造器/生成器类,通过传递大类型信息来获取工厂 2.策略模式(侧重于行为的封装) 3.观察者模式(发布/订阅模型) 4.责任链模式(请求沿着链向下传递)...

猜你喜欢

常见的设计模式

一、单例设计模式 饿汉式: 懒汉式:...

常见的设计模式

单例模式 设计原则: 1.单一职责原则: 又称单一功能原则。所谓职责是指类变化的原因。如果一个类有 多于一个的动机被改变,那么这个类就具有多于-一个的职责。 而单一-职责原则就是指一 一个类或者模块应该有且只有一个改变的原因。 2.开放封闭原则: 是所有面向对象原则的核心。其核心的思想是:软件实体应该是可扩展,而不可修改的。 也就是说,对扩展是开放的,而对修改是封闭的。主要体现在两个方面: -对扩...

常见的设计模式

常见的设计模式 单例模式 饿汉模式 懒汉模式 懒汉模式+synchronized 懒汉模式+双重校验模式 工厂模式 简单工厂模式 工厂方法 适配器模式 类适配器模式 对象适配器模式 装饰器模式 代理模式 静态代理模式 动态代理模式 不变模式 单例模式 在某些情况下,整个程序运行过程中只允许出现类的一个实例,但又经常频繁销毁和创建的对象,尤其是一些重量级对象,此时我们只需要创建一个对象实例,比如全局...

PHP中5种常见的设计模式

单例模式 所谓单例模式,就是确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例,即在应用程序中只会有这个类的一个实例存在。 通常单例模式用在仅允许数据库访问对象的实例中,从而防止打开多个数据库连接,单例模式是一种常见的设计模式,在计算机系统中,线程池、缓存、日志对象、对话框、打印机、数据库操作、显卡的驱动程序常被设计成单例。 一个单例类应包括以下几点: 和普通类不同,单例类不能被直接实...

PHP实现11中常见的设计模式

1 工厂模式 使用工厂方法或者类生成对象,而不是在代码中直接new 2 单例模式 类对象仅允许创建一个 构造方法声明为私有 3 注册模式 全局共享和交换对象 4 适配器模式 将不同的函数接口封装成统一的API,比如: 数据库适配器:mysql、mysqli、pdo 缓存适配器:file、redis、memcache 5 策略模式 将一组特定的行为和算法封装成类,以适应某些特定的上下文环境,比如首页...