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();
          }
      }
    

工厂模式

  • 1、特点

      隐藏复杂的逻辑处理过程,只关心执行结果。
      简单工厂、工厂方法、抽象工厂
      任督二脉
      
      实现统一管理,专业化管理
      如果没有工厂模式,小作坊,没有执行标准的
      如果买到三无产品(没有标准)
      工厂接口,就定义了所有工厂的执行标准
      例:
      	码农就是执行标准的人
      	系统架构师,就是制定标准的人
      设计模式的经典之处,就在于,解决了编写代码的人和调用代码的人双方的痛处
      解决了我们的双手
    
  • spring中的工厂模式

Bean
BeanFactory(生产Bean)
单例的Bean
被代理过的Bean
最原始的Bean(原型)
List类型的Bean
作用域不同的Bean
getBean
非常的紊乱,维护困难
解耦(松耦合开发)

  • 举例

1、公共接口与类:

public interface Car {

    void getName(Car car);
}


public class Bmw implements Car{

    public void getName(Car car) {
        System.out.println("Bmw Car...");
    }
}


public class Benz implements Car{

    public void getName(Car car) {
        System.out.println("Benz Car...");
    }
}


public class Audi implements Car{

    public void getName(Car car) {
        System.out.println("Audi Car...");
    }
}

1.1、简单工厂模式:

public class SimpleFactory {

    /**
     * 通过输入参数判断是什么汽车厂商
     * @param name
     * @return 汽车厂商
     */
    public Car getName(String name){
        if(name.equalsIgnoreCase("BMW")){
            System.out.println("BMW Car...");
            return new Bmw();
        }else if(name.equalsIgnoreCase("BENZ")){
            System.out.println("BENZ Car...");
            return new Benz();
        }else if(name.equalsIgnoreCase("AUDI")){
            System.out.println("AUDI Car...");
            return new Audi();
        }else {
            System.out.println("没有您要找的汽车生产厂商...");
            return null;
        }
    }
}


public class SimpleFactoryTest {

    public static void main(String[] args) {
        new SimpleFactory().getName("benz");
    }
}

1.2 工厂方法模式:

public interface FuncFactory {
    Car getCar();
}


public class BmwFactory implements FuncFactory{

    public Car getCar() {
        System.out.println("func bmw car ...");
        return new Audi();
    }
}


public class BenzFactory implements FuncFactory{
    public Car getCar() {
        System.out.println("func benz car ...");
        return new Benz();
    }
}


public class AudiFactory implements FuncFactory{
    public Car getCar() {
        System.out.println("func audi car ...");
        return new Audi();
    }
}


public class FuncFactoryTest {

    public static void main(String[] args) {
        FuncFactory factory = new BmwFactory();
        factory.getCar();
    }
}

1.3 抽象工厂模式:

public abstract class AbstractFactory {

    public abstract Car getCar();

    /**
     * 通过输入参数判断是什么汽车厂商
     * @param name
     * @return 汽车厂商
     */
    public Car getCar(String name){
        if(name.equalsIgnoreCase("BMW")){
            return new BmwFactory().getCar();
        }else if(name.equalsIgnoreCase("BENZ")){
            return new BenzFactory().getCar();
        }else if(name.equalsIgnoreCase("AUDI")){
            return new AudiFactory().getCar();
        }else {
            System.out.println("没有您要找的汽车生产厂商...");
            return null;
        }
    }
}


public class AudiFactory extends AbstractFactory {
    public Car getCar() {
        System.out.println("abst audi car ...");
        return new Audi();
    }
}


public class BenzFactory  extends AbstractFactory  {
    public Car getCar() {
        System.out.println("abst benz car ...");
        return new Benz();
    }
}


public class BmwFactory  extends AbstractFactory  {

    public Car getCar() {
        System.out.println("abst bmw car ...");
        return new Audi();
    }
}


public class DEfaultFactory extends AbstractFactory{
    private static final BenzFactory factory = new BenzFactory();
    public Car getCar() {
        return factory.getCar();
    }
}


public class AbstractFactoryTest {

    public static void main(String[] args) {
        DEfaultFactory factory = new DEfaultFactory();
        factory.getCar("bmw");
    }
}

单例模式

2WH(人都是天生的惰性)

  • 穷举法:

      配置文件:如果不是单例(针对于某一种功能的配置)
      (两个配置文件中的内容一样的,则有一个是浪费的
      如果是不一样的,我们就不知道以哪个为准了)
      直接上级领导:(对于你来说,如果有多个领导,你到底听谁的? 选择恐惧症)
      日历:(不严谨)在中国,是有两种日历同时存在的
      阴历(农历,一般用于指导农业生产,二十四节气)
      和阳历(公历,一般用于国际交流、企事业单位的工作指导)
      (在万千世界中,即使是一片小小的树叶,他们都是长得不一样的)
      是什么?为什么要有单例模式?单例具体怎么实现?
    
  • 特点:

      1、保证从系统启动到系统终止,全过程只会产生一个实例。
      2、当我们在应用中遇到功能性冲突的时候,需要使用单例模式。
    

常用写法:

public class Singleton1 {

    //私有化构造
    private Singleton1(){}

    //定义一个内部类,用于对象的返回
    private static final class LazyLoadler {
        private static final Singleton1 INSTANCE = new Singleton1();
    }

    public static Singleton1 getInstance(){
        return LazyLoadler.INSTANCE;
    }
}

委派模式

要和代理模式区分开来

  • 2WH,和代理模式区分开来,什么是2WH?

      What:两个角色,受托人,委托人(社会上是平等关系)
      公司里面:项目经理,普通员工(法律上平等的,工作的关系,各自的职责会不一样)
      干活是我的,功劳是你的(最重要的特点)
      项目经理(委托人):主要职责是安排任务
      普通员工(受托人):执行任务
    
  • 特点:

      1、类似于中介的功能(委托机制);
      2、持有被委托人的引用。
      3、不关心过程,只关心结果。
      Why? 主要目的就是隐藏具体实现逻辑
      IOC 容器中,有一个 Register 的东西(为了告诉我们的容器,在这个类被初始化的过程中,需要做很多
      不同的逻辑处理,需要实现多个任务执行者,分别实现各自的功能)
      保证结果的多样性,对于用户来是只有一种方法
    
  • 举例:

      /**
       * @Author: Steven.yu
       * @Description: 执行者接口
       * @CreateTime: 2020/08/31 14:15:04
       */
      public interface IExecutor {
      
          void doing();
      }
    
    
      public class Executor1 implements IExecutor {
          public void doing() {
              System.out.println("我是员工1");
          }
      }
    
    
      public class Executor2 implements IExecutor {
          public void doing() {
              System.out.println("我是员工2");
          }
      }
    
    
      public class ManagerExecutor implements IExecutor{
      
          private static IExecutor executor;
      
          public ManagerExecutor(IExecutor executor){
              this.executor = executor;
          }
      
          public void doing() {
              this.executor.doing();
          }
      }
    
    
      public class ExecutorTest {
      
          public static void main(String[] args) {
              ManagerExecutor managerExecutor = new ManagerExecutor(new Executor1());
              managerExecutor.doing();
          }
      }
    

策略模式

概念:过程不同,但结果一样。

在这里插入图片描述

原型模式

概念:数据内容完全一样,但实例不同。
就是一个现成的对象,这个对象里面有已经设置好的值
当我要新建一个对象,并且要给新建的对象赋值,而且赋值内容要分之前的一模一样。

能够直接拷贝其实际内容的数据类型/只支持9种,8大基本类型和String,浅拷贝。
  • 举例:

      /**
       * @Author: Steven.yu
       * @Description: 金箍棒实体
       * @CreateTime: 2020/09/02 15:14:08
       */
      package com.gupaoedu.vip.prototype;
      
      import java.io.Serializable;
      
      public class GoldenCudgel implements Serializable {
      
          /**
           * 高度
           */
          private Integer height;
      
          /**
           * 直径
           */
          private Integer diameter;
      
          public Integer getHeight() {
              return height;
          }
      
          public void setHeight(Integer height) {
              this.height = height;
          }
      
          public Integer getDiameter() {
              return diameter;
          }
      
          public void setDiameter(Integer diameter) {
              this.diameter = diameter;
          }
      
          /**
           * 金箍棒长大
           */
          public void graw(){
              this.diameter *= 2;
              this.height *= 2;
          }
      
          /**
           * 金箍棒缩小
           */
          public void narrow(){
              this.diameter /= 2;
              this.height /= 2;
          }
      }
    
    
      public class Monkey implements Serializable {
      
          /**
           * 姓名
           */
          private String name;
      
          /**
           * 年龄
           */
          private Integer age;
      
          /**
           * 出生日期
           */
          private Date date;
      
          public Monkey() {
          }
      
          public Monkey(String name, Integer age, Date date) {
              this.name = name;
              this.age = age;
              this.date = date;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public Integer getAge() {
              return age;
          }
      
          public void setAge(Integer age) {
              this.age = age;
          }
      
          public Date getDate() {
              return date;
          }
      
          public void setDate(Date date) {
              this.date = date;
          }
      }
    
    
      /**
       * @Author: Steven.yu
       * @Description: 齐天大圣
       * @CreateTime: 2020/09/02 15:18:51
       */
      package com.gupaoedu.vip.prototype;
      
      import java.io.*;
      import java.util.Date;
      
      public class GreatSage extends Monkey implements Cloneable,Serializable{
      
          /**
           * 金箍棒
           */
          private GoldenCudgel cudgel;
      
          public GoldenCudgel getCudgel() {
              return cudgel;
          }
      
          public void setCudgel(GoldenCudgel cudgel) {
              this.cudgel = cudgel;
          }
      
          public GreatSage(){
              this.setName("yuhai");
              this.setAge(22);
              this.setDate(new Date());
          }
      
          public void change(){
              System.out.println("大圣本尊的出生日期是:" + this.getDate().getTime());
              GreatSage clone = (GreatSage)this.clone();
              System.out.println("克隆大圣的出生日期是:" + clone.getDate().getTime());
              System.out.println("大圣本尊和克隆大圣是否为同一个对象:" + (this == clone));
              System.out.println("大圣本尊的金箍棒和克隆大圣的金箍棒是否为同一个对象:" + (this.cudgel == clone.cudgel));
          }
      
      
      
          @Override
          protected Object clone() {
              ByteArrayOutputStream baos = null;
              ObjectOutputStream oos = null;
              ByteArrayInputStream bais = null;
              ObjectInputStream ois = null;
              try {
                  baos = new ByteArrayOutputStream();
                  oos = new ObjectOutputStream(baos);
                  oos.writeObject(this);
      
                  bais = new ByteArrayInputStream(baos.toByteArray());
                  ois = new ObjectInputStream(bais);
                  GreatSage greatSage = (GreatSage)ois.readObject();
                  greatSage.setDate(new Date());
                  greatSage.setCudgel(new GoldenCudgel());
                  return greatSage;
              } catch (Exception e) {
                  return null;
              }finally {
                  try{
                      oos.close();
                      baos.close();
                      ois.close();
                      bais.close();
                  }catch (Exception e){
      
                  }
              }
          }
      }
    
      public class GreatSageTest {
      
          public static void main(String[] args) {
              GreatSage greatSage = new GreatSage();
              greatSage.change();
          }
      }
    

在这里插入图片描述

模板模式

概念:执行流程固定,但中间有些步骤有细微差别。

  • 举例:

      public abstract class Water {
      
          public void print(){
              mainMaterials();
              System.out.println("加入100°的沸水,泡2-3分钟");
              accessories();
              System.out.println("开始品尝");
          }
      
          /**
           * 准备主料
           */
          public abstract void mainMaterials();
      
          /**
           * 准备辅料
           */
          public abstract void accessories();
      }
    
    
      public class GreenTea extends Water {
          public void mainMaterials() {
              System.out.println("准备绿茶茶叶...");
          }
      
          public void accessories() {
              System.out.println("清理绿叶...");
          }
      }
    
    
      public class MilkTea extends Water {
          public void mainMaterials() {
              System.out.println("准备优乐美奶茶...");
          }
      
          public void accessories() {
              System.out.println("加入辅料...");
          }
      }
    
    
      public class WaterTest {
      
          public static void main(String[] args) {
              Water water = new MilkTea();
              water.print();
          }
      }
    

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值