栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/439551.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号