简体   繁体   English

Spring-单例bean内的原型bean

[英]Spring - prototype bean inside a singleton bean

Spring has bean types/scopes like 春天有豆类/范围像
-singleton bean (only one bean per application context) -singleton bean(每个应用程序上下文仅一个bean)
-prototype bean (a new bean per request) -prototype bean(每个请求一个新bean)

Now if there is a reference to prototype bean inside a singleton bean, is there a way to get a new prototype bean (which is inside the singleton bean) on every request to the singleton bean. 现在,如果在单例Bean中引用了原型Bean,则有一种方法可以在对单例Bean的每次请求中获取新的原型Bean(位于单例Bean内)。
If yes, what would the configurations look like? 如果是,那么配置会是什么样?

There is a way with lookup-method like this: 查找方法有如下方法:

import org.springframework.beans.factory.annotation.Lookup;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

public final class Main {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
        for (int i = 0; i < 10; i++) {
            System.out.println(i + ".- call: " + applicationContext.getBean(Singleton.class));
        }
    }

    @ComponentScan("foo")
    @Configuration
    public static class Config {

    // It's important to define SingletonBase component with @Component annotation and not here, If you define SingletonBase initialization here, It'll not work!

        @Bean
        @Scope(BeanDefinition.SCOPE_PROTOTYPE)
        public Prototype prototype() {
            return new PrototypeBase();
        }
    }

    public interface Prototype {

        public long getInstanceId();
    }

    public interface Singleton {

        public Prototype getPrototype();
    }

    // It's important define SingletonBase component as this, If you define SingletonBase initialization inside a factory it'll not work!
    @Component
    public static class SingletonBase implements Singleton {

        private static long instanceIdGenerator = 1L;
        private long instanceId = generateId();

        private static synchronized long generateId() {
            return instanceIdGenerator++;
        }

        public SingletonBase() {
            System.out.println("Singleton initialized!");
        }

        @Override
        public String toString() {
            return "SingletonBase{" + "instanceId=" + instanceId + ", prototypeId=" + getPrototype().getInstanceId() + '}';
        }

        @Override
        @Lookup
        public Prototype getPrototype() {
            return null;
        }
    }

    public static class PrototypeBase implements Prototype {

        private static long instanceIdGenerator = 1L;
        private long instanceId = generateId();

        private static synchronized long generateId() {
            return instanceIdGenerator++;
        }

        public PrototypeBase() {
            System.out.println("Prototype initialized!");
        }

        public long getInstanceId() {
            return instanceId;
        }
    }
}

It prints: 它打印:

Singleton initialized!
Prototype initialized!
0.- call: SingletonBase{instanceId=1, prototypeId=1}
Prototype initialized!
1.- call: SingletonBase{instanceId=1, prototypeId=2}
Prototype initialized!
2.- call: SingletonBase{instanceId=1, prototypeId=3}
Prototype initialized!
3.- call: SingletonBase{instanceId=1, prototypeId=4}
Prototype initialized!
4.- call: SingletonBase{instanceId=1, prototypeId=5}
Prototype initialized!
5.- call: SingletonBase{instanceId=1, prototypeId=6}
Prototype initialized!
6.- call: SingletonBase{instanceId=1, prototypeId=7}
Prototype initialized!
7.- call: SingletonBase{instanceId=1, prototypeId=8}
Prototype initialized!
8.- call: SingletonBase{instanceId=1, prototypeId=9}
Prototype initialized!
9.- call: SingletonBase{instanceId=1, prototypeId=10}   

Inject the ApplicationContext in the singleton bean and use the getBean method to get the prototype. 将ApplicationContext注入单例bean中,并使用getBean方法获取原型。

@Autowired
private ApplicationContext ctx;

public void request() {
    MyProptotypeBean mpb = this.ctx.getBean(MyProptotypeBean.class);//new instance for evety call to the method
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM