spring的单例对象注入多例对象

一、Method Injection
1、通常通过将一个bean定义为另一个bean的属性来处理依赖关系。当bean的生命周期不同时,假设单例beanB需要使用非单例(原型)beanA,可能是在B的方法调用上。会出现问题,BeanA和BeanB都变成单例作用域。
例子:
创建一个bean对象BeanA(对象的作用域为多例)

package com.it.app.MethodI;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("prototype")
public class BeanA {
}

创建一个bean对象BeanB(对象为单例,且依赖BeanA)

package com.it.app.MethodI;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("singleton")
public class BeanB {

    @Autowired
    private BeanA beanA;

    public void getBeanHash() {
        System.out.println("beanB的hash值: " + this.hashCode());
        System.out.println("beanA的hash值: " + beanA.hashCode());

    }

}

配置一个扫描BeanA、BeanB对象的类,@ComponentScan注解扫描两个对象所在包下放到容器中。

package com.it.app.config;

import org.springframework.context.annotation.ComponentScan;

@ComponentScan("com")
public class AppConfig {
}

打印BeanA、BeanB对象的hash值,并且打印对象hash值,启动容器:

package com.it.app;

import com.it.app.MethodI.BeanB;
import com.it.app.config.AppConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AppFour {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        BeanB beanB = (BeanB) context.getBean("beanB");
        beanB.getBeanHash();
        beanB.getBeanHash();

    }

}

测试结果:

beanB的hash值: 583015088
beanB的hash值: 1091781053
beanB的hash值: 583015088
beanB的hash值: 1091781053

测试结果发现单例对象BeanB一直是同一个值是单例,而BeanA作为多例对象注入到BeanA中时,也变成单例对象。hash值相同。
2、解决方法
(1)通过ApplicationContextAware接口
修改对象BeanB对象:

package com.it.app.MethodI;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("singleton")
public class BeanB implements ApplicationContextAware {

    private  ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
      this.applicationContext = applicationContext;
    }
    
    public void getBeanHash() {
        System.out.println("beanB的hash值: " + this.hashCode());
        System.out.println("beanA的hash值: " +this.applicationContext.getBean("beanA", BeanA.class).hashCode());

    }

}

测试结果:BeanA作用域为多例(官网说提示:该操作是不可取的,因为业务代码知道Spring框架并与之耦合)。

beanB的hash值: 502891368
beanA的hash值: 566891420
beanB的hash值: 502891368
beanA的hash值: 577734751

(2) Lookup Method Injection (通过@Lookup注解)
修改BeanB对象

package com.it.app.MethodI;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Lookup;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("singleton")
public abstract class BeanB  {


    @Lookup
    public  abstract BeanA createBeanA();


    public void getBeanHash() {
        System.out.println("beanB的hash值: " + this.hashCode());
        System.out.println("beanA的hash值: " +createBeanA().hashCode());

    }

}

输出结果值:

beanB的hash值: 49547843
beanA的hash值: 1417554340
beanB的hash值: 49547843
beanA的hash值: 478182173
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值