单例注入多例


      Spring bean容器中的bean有单例bean,也有多例bean。当我们需要给一个单例beanA注入一个单例beanB,或者给一个多例beanA注入一个多例或单例beanB时,都可以通过配置让Spring的bean容器帮我们完成。但如果我们需要给一个单例beanA注入一个多例beanB时,仅仅通过配置Spring是无法帮我们的单例beanA注入一个多例beanB的,即无法让我们每次使用beanB时都使用的是一个全新的beanB。因为beanA只初始化一次,相对应的Spring只会给beanA注入一个beanB。解决办法是给beanA注入一个ApplicationContext,这样我们就可以在每次需要使用beanB时都从ApplicationContext中获取一个新的beanB。
      注入ApplicationContext有两种方式,实现ApplicationContextAware接口和通过@Autowired或@Resource注解标注让Spring进行自动注入。
     

实现ApplicationContextAware接口
       ApplicationContextAware接口中定义一个setApplicationContext()方法,对于实现了该接口的bean,Spring将通过调度对应的setApplicationContext()方法将当前ApplicationContext传递过去。

public class Hello implements ApplicationContextAware {
    
    private ApplicationContext applicationContext;

    /**
     * Spring将通过该方法给我们的bean注入当前的ApplicationContext
     */
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
    
}

通过注解标注
  在使用注解进行配置时,我们也可以通过注解来告诉Spring要为当前的bean注入哪些内容。对于ApplicationContext也是一样的,可以通过对应的注解来告诉Spring将为我们注入对应的ApplicationContext。自动注入的注解可以是@Resource,也可以是@Autowired。

public class Hello {
    
    private ApplicationContext applicationContext;

    @Resource
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
    
}

Spring有一种机制,可以动态的实现或重写bean容器中指定bean的指定方法,然后将返回值指定为bean容器中的另一个bean

1、在beanA对应的类中定义一个方法用来获取BeanB,有这么一个方法就行,可以是空实现,到时候将由Spring来为我们重写或实现,然后返回一个BeanB类型的bean。为此,可以将我们的BeanA如下定义:

public class BeanA {

    /**
     * 需要使用到BeanB的方法
     */
    public void doSomething() {
        BeanB beanB = this.getBeanB();
        System.out.println(beanB);
        //...
    }
    
    /**
     * 定义一个返回值为BeanB的方法,用来获取BeanB类型的bean,该方法将由Spring来重写。
     * @return
     */
    public BeanB getBeanB() {
        return null;
    }
    
}

2、在ApplicationContext中定义一个单例beanA和一个多例beanB,同时通过lookup-method元素指定beanAgetBeanB方法将会被Spring重写并返回bean容器中的beanB

    <bean id="beanB" class="com.app.BeanB" scope="prototype"/>
    <bean id="beanA" class="com.app.BeanA">
        <!-- 表示将由Spring重写getBeanB()方法,并返回名为beanB的bean -->
        <lookup-method name="getBeanB" bean="beanB"/>
    </bean>

  经过以上两步以后每次在调度beanA的getBeanB()方法时,Spring都重新从bean容器中获取一个beanB,因为beanB定义为多例形式,所以每次都会获取一个全新的BeanB对象。

  在给一个bean指定了lookup-method后,Spring将通过CGLIB动态的生成一个该bean对应类型的子类,然后在该子类中实现或重写lookup-method元素指定的方法,并从bean容器中获取lookup-method元素指定的bean作为返回值进行返回。

      当bean指定的类型是一个抽象类且lookup-method指定的方法是一个抽象方法时,Spring就将实现该抽象方法,否则就是重写。定义lookup-method的bean真正的类型是Spring动态生成类的类型,但是它可以被当做bean本身指定的类型使用,因为动态生成的类就是继承自bean本身指定的类型的。

  由于Spring是需要动态生成类来重写或实现指定的方法的,所以我们必须确保由lookup-method指定的方法是可以被重写的,这就要求该方法对子类是可访问的,而且不能是final型的。具体来讲lookup-method元素指定的方法需要具有如下形式:

<public|protected> [abstract] <return-type> methodName(no-arguments)

      如你所见,lookup-method指定的方法还不能有参数。

参考:

     https://blog.csdn.net/elim168/article/details/74915352 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM