使用同类服务需要注入多个bean的便捷封装

服务Bean缓存封装

前提: 使用到某类服务时可能会需要注入这类服务的所有的bean, 每次注入都很麻烦, 可以通过封装一个这类服务的bean的缓存来便捷获取到对应的bean的类.

package com.imooc.ad.index;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.PriorityOrdered;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Auther: louye
 * @Date: 2022/10/3 14:43
 * @Description:
 * 对于一类服务有需要同时注入多个bean的时候, 可以通过一个缓存bean来对需要注入的bean进行封装,
 * 每次需要使用到这类服务就可以直接使用这个缓存bean, 然后再在要使用的地方通过class来获取缓存bean
 */
@Component
public class DataTable implements ApplicationContextAware, PriorityOrdered {

    private static ApplicationContext applicationContext;

    public static final Map<Class, Object> dataTableMap = new ConcurrentHashMap<>();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        DataTable.applicationContext = applicationContext;
    }

    @Override
    public int getOrder() {
        return PriorityOrdered.HIGHEST_PRECEDENCE;
    }

    @SuppressWarnings("all")
    public static <T> T of(Class<T> clazz) {
        T instance = (T) dataTableMap.get(clazz);
        if (instance != null) {
            return instance;
        }
        dataTableMap.put(clazz, bean(clazz));
        return (T) dataTableMap.get(clazz);
    }

    @SuppressWarnings("all")
    private static <T> T bean(String beanName) {
        return (T) applicationContext.getBean(beanName);
    }

    @SuppressWarnings("all")
    private static <T> T bean(Class clazz) {
        return (T) applicationContext.getBean(clazz);
    }
}

<think>好的,我现在需要解决用户在Spring框架中关于多次注入一个bean的问题。用户问的是多次注入同一bean是否有影响,以及正确使用方式。我需要结合提供的引用内容来回答。 首先,回顾引用内容。引用1提到单例bean的属性在注入时只赋值一次,即使原型bean注入到单例中,每次获取的实例可能相同。引用3指出单例bean在初始化时创建,而原型bean每次getBean会创建新实例,但注入到单例中的原型bean可能只初始化一次。引用4提到通过工厂bean注入时,单例模式下多次获取的是同一实例。 接下来,用户的问题核心是多次注入一个bean的影响。这里需要区分单例和原型作用域。如果是单例bean,多次注入其实是同一个实例,不会有问题,因为Spring默认管理单例。但如果是原型bean,每次注入是否生成新实例? 根据引用1和3,当原型bean注入到单例bean中时,由于单例的初始化只发生一次,所以原型bean注入时只会被实例化一次,导致即使原型bean的作用域是prototype,单例中持有的引用还是同一个实例。这时候多次注入可能不会按预期生成新实例,需要特别处理,比如使用方法注入或Lookup注解。 另外,引用2提到了当有多个同类bean时,注入会报错,需要用@Primary或@Qualifier解决。但用户的问题是多次注入一个bean,而不是多个同类bean的问题,所以这可能不直接相关,但可以作为正确使用方式的一部分,确保注入时明确指定。 正确使用方式包括:根据作用域选择单例或原型,避免在单例中直接注入原型bean导致实例无法更新,使用Provider或Lookup注解实现每次获取新实例。同时,确保注入点明确,避免歧义。 总结,多次注入一个单例bean不会有问题,但如果是原型bean,需要注意注入上下文,可能需要额外配置才能每次获取新实例。需要分情况讨论,并给出解决方案。</think>在Spring框架中多次注入一个Bean是否会产生影响,需要根据Bean的作用域和注入方式具体分析。以下是关键要点和正确使用方式: --- ### 一、单例Bean多次注入的情况 1. **默认行为** Spring默认作用域为单例(`singleton`),无论注入多少次,容器中**始终只有一个实例**。 ```java @Service public class ServiceA { @Autowired // 注入单例Bean private ServiceB serviceB; } @Service public class ServiceC { @Autowired // 再次注入一个单例Bean private ServiceB serviceB; } ``` - `ServiceB`的实例在`ServiceA`和`ServiceC`中是同一个对象[^1][^4]。 2. **无副作用** 单例Bean的属性和状态会被所有依赖它的组件共享,需注意线程安全问题。 --- ### 二、原型Bean多次注入的情况 1. **默认行为** 原型作用域(`prototype`)的Bean每次注入时会**生成新实例**: ```java @Scope("prototype") @Component public class PrototypeBean { /*...*/ } @Service public class ServiceD { @Autowired // 实例1 private PrototypeBean prototypeBean; } @Service public class ServiceE { @Autowired // 实例2(与ServiceD中的不同) private PrototypeBean prototypeBean; } ``` 2. **特殊场景下的问题** 若**原型Bean注入到单例Bean中**,由于单例Bean只初始化一次,其依赖的原型Bean也会被固定为初始注入的实例,后续不会更新: ```java @Service public class SingletonService { @Autowired private PrototypeBean prototypeBean; // 仅初始化一次! } ``` 此时多次调用`SingletonService`中的`prototypeBean`,实际使用的是同一个实例[^1][^3]。 --- ### 三、正确使用方式 1. **明确Bean的作用域** - 单例Bean:适合无状态服务(如工具、配置)。 - 原型Bean:适合有状态且需要隔离的组件(如用户会话)。 2. **解决单例依赖原型的问题** - **方法1:通过`Provider`延迟获取** ```java @Autowired private Provider<PrototypeBean> prototypeBeanProvider; public void doSomething() { PrototypeBean bean = prototypeBeanProvider.get(); // 每次生成新实例 } ``` - **方法2:使用`@Lookup`注解** ```java @Lookup public PrototypeBean getPrototypeBean() { return null; // Spring会动态生成实现 } ``` 3. **避免注入歧义** 当存在多个同类Bean时,需使用`@Qualifier`或`@Primary`明确指定: ```java @Autowired @Qualifier("specificBean") private TestService testService; ``` 否则会抛出`NoUniqueBeanDefinitionException`[^2]。 --- ### 四、总结 | 场景 | 单例Bean | 原型Bean | |-----------------------|----------|----------------------| | 多次注入到不同单例中 | 无影响 | 需通过Provider/Lookup | | 多次注入到同一单例中 | 无影响 | 需通过Provider/Lookup | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值