Spring 多实例注入
文章目录1. Spring 多实例注入的应用2. Spring 多实例注入的使用1. Spring 多实例注入的应用Spring 容器中保存的 bean 默认是单例的,通常来说这样做可以降低 bean 对象创建的频率,在某些访问量大的场景下可以节省对象创建消耗的时间,提高响应性能。但在一些其他场景,比如脚本调度处理多个消息队列中的消息,这时候拉取各个队列消息的步骤是完全相同的,只不过各条队列的..
文章目录
1. Spring 多实例注入的应用场景
Spring 容器中保存的 bean 默认是单例的,通常来说这样做可以降低 bean 对象创建的频率,在某些访问量大的场景下可以节省对象创建消耗的时间,提高响应性能。但在一些其他场景,比如脚本调度处理多个消息队列中的消息,这时候拉取各个队列消息的步骤是完全相同的,只不过各条队列的名称和密码不一样,显然可以使用一个专门的 processor
来处理,以便减少重复代码。这样一来,一个解决方式是每一条队列使用一个单独的processor
实例,这就需要用到 Spring 的多实例注入了
2. Spring 多实例注入的使用
Spring 框架中, 可以通过在一个Java 类上添加注解 @Scope
并配置注解相关属性将该类声明为 原型作用域
,这样每次从 Spring 容器中获取其实例的时候都会返回一个新的对象
2.1 通过 ApplicationContext 获取多实例
如果在一个Java 类上只添加注解 @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
,这种声明为多实例的 bean 对象通过注解 @Resource
和 @Autowired
自动注入无法保证每次获取的都是新的实例,一个解决方法是通过 Spring 的 ApplicationContext
,直接获取容器中的 bean 实例,示例代码如下
-
首先在目标类上添加注解
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
声明其每次使用都需要新的实例@Component @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class MessageProcessor { ...... private String queueName; private String passWord; ...... }
-
创建实现
ApplicationContextAware
接口的SpringBeanProvider
工具类。使用时注入SpringBeanProvider
实例,调用其getBean()
方法,传入指定参数即可获取到类的新实例@Component public class SpringBeanProvider implements ApplicationContextAware { private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } /** * 通过 beanName 获取 Bean * @param beanName * @return */ public Object getBean(String beanName) { return applicationContext.getBean(beanName); } /** * 通过class获取Bean * @param clazz * @param <T> * @return */ public <T> T getBean(Class<T> clazz) { return applicationContext.getBean(clazz); } /** * 通过 beanName ,以及Clazz返回指定的Bean * @param beanName * @param clazz * @param <T> * @return */ public <T> T getBean(String beanName, Class<T> clazz) { return applicationContext.getBean(beanName, clazz); } }
2.2 配置 @Scope 的 proxyMode 属性获取多实例
这种方式需要在实现类上添加注解@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
指定类的代理模式,这样使用注解 @Resource
和 @Autowired
自动注入也能保证每次方法调用都是基于新对象,其底层实现原理是基于 AOP 机制
- 使用
ScopedProxyFactoryBean
作为代理类替换掉目标类,生成相应的 BeanDefintion 注册到容器中- 上层应用获取目标类实例时,实际最终获取到代理类
ScopedProxyFactoryBean
实例ScopedProxyFactoryBean
作为目标实例代理对象,其每次方法调用时会触发拦截器执行,在拦截器逻辑中会通过BeanFactory#getBean()
方法新建目标对象,从而实现多例
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MessageProcessor {
......
private String queueName;
private String passWord;
......
}
更多推荐
所有评论(0)