• springboot中使用原型模式(二)


    参考:

    https://blog.csdn.net/qq_25863845/article/details/123475147

    https://www.bbsmax.com/A/pRdBa7E25n/

    一、单例对象依赖原型对象

    springboot中大部分都是单例,如果一个单例对象中注入了另一个原型对象,那么使用Autowired得到的还是一个单例对象。

    原因是单例对象只有一次对象初始化的机会,所以它只能得到第一次注入的原型对象,后面无法再改。

    如下:

    //car是一个单例
    @Component
    public class Car {
        @Autowired
        private Seat seat;
    
        public Seat getSeat() {
            return seat;
        }
    }
    
    @Component
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public class Seat {
    
    }

    Seat我们定义它是一个原型模式。

    测试一下,看是否符合预期

    @SpringBootTest(classes= MetaCenterApplication.class)
    class SeatFactoryTest {
    
    
        @Autowired
        private Car car;
    
        @Test
        void get() {
            Seat king = car.getSeat();
            Seat king1 = car.getSeat();
            System.out.println(king);
            System.out.println(king1);
        }
    }

    输出:

    cn.jinka.gcdp.metacenter.application.metadata.Seat@12ec5e73
    cn.jinka.gcdp.metacenter.application.metadata.Seat@12ec5e73

    显而易见,Seat也变成单例了,那怎么办?

    还好springboot给我们提供了@LookUp

    我们将Car改造一下

    @Component
    public class Car {
        //这个地方返回null即可,spring会帮我们实现
        @Lookup
        public Seat getSeat(){
            return null;
        }
        
    }

    重新测试执行一下,发现已经生成了两个不同的对象:

    cn.jinka.gcdp.metacenter.application.metadata.Seat@689504b1
    cn.jinka.gcdp.metacenter.application.metadata.Seat@bf2f2ce

    二、原型对象有多个实现类

    假如我们的Seat有多种类型,真皮座椅、绒布座椅等等,这个时候可以构造一个抽象工厂类专门生成椅子。

    //抽象椅子
    public abstract class Seat {
    
    }
    //真皮座椅
    @Component("SeatA")
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public class SeatA extends Seat{
    
    }
    
    //绒布座椅
    @Component("SeatB")
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public class SeatB extends Seat{
    
    }

    椅子工厂,每次都给汽车生产最新的椅子,@Lookup的参数就是类上面@Component的name

    //抽象工厂方法
    @Component
    public abstract class SeatFactory {
    
    
        @Lookup("SeatA")
        protected abstract Seat getSeatA();
    
        @Lookup("SeatB")
        protected abstract Seat getSeatB();
    
    }

    汽车类

    @Component
    public class Car {
    
        @Autowired
        private SeatFactory seatFactory;
    
        public Seat getSeat(){
            return seatFactory.getSeatA();
        }
    
    }

    测试类

    @SpringBootTest(classes= MetaCenterApplication.class)
    class SeatFactoryTest {
    
    
        @Autowired
        private Car car;
    
        @Test
        void get() {
            Seat king = car.getSeat();
            Seat king1 = car.getSeat();
            System.out.println(king);
            System.out.println(king1);
        }
    }

    输出:

    cn.jinka.gcdp.metacenter.application.metadata.SeatA@4c343088
    cn.jinka.gcdp.metacenter.application.metadata.SeatA@504ccf42

    可以发现,我们通过@Lookup得到了SeatA类型的实例,而且每次生成的都是新的。

    备注:

    @Lookup底层的实现逻辑还是通过applicationContext.getBean(ClassB.class)这种方式实现的。

    @Component
    public class ClassA implements ApplicationContextAware {
        private ApplicationContext applicationContext;
        public void printClass() {
            System.out.println("This is Class A: " + this);
            getClassB().printClass();
        }
        public ClassB getClassB() {
            return applicationContext.getBean(ClassB.class);
        }
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext = applicationContext;
        }
    }
  • 相关阅读:
    append 注意事项
    列表与字符串转换
    删除列表元素
    段寄存器
    通用寄存器
    最强大的王爽汇编语言学习环境使用教程
    JavaScript获取输入框内容
    ubuntu16.04中将python3设置为默认
    Django之cookie和session
    postman 安装桌面版
  • 原文地址:https://www.cnblogs.com/wangbin2188/p/16469635.html
Copyright © 2020-2023  润新知