开发环境:IntelliJ IDEA 2019.2.2
Spring Boot版本:2.1.8
新建一个名称为demo的Spring Boot项目。
一、限定注解
当存在多个同类型的bean时,可以使用Primary注解指定优先注入的bean。如果对bean的注入选择做进一步的控制,则可以使用限定注解。
限定注解可以与特定的参数关联起来,缩小类型匹配的范围,最后选择一个符合条件的bean来注入。
1、新建类 MyBean.java
package com.example.demo;
public class MyBean {
public MyBean(String id){
this.id = id;
}
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
2、新建类 MyConfig.java
package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfig {
@Bean
public MyBean bean1(){
return new MyBean("1");
}
@Bean
public MyBean bean2(){
return new MyBean("2");
}
}
3、新建一个控制器 DemoController.java
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@Autowired
@Qualifier("bean1")
MyBean bean;
@RequestMapping(value = "/")
public String index(){
return bean.getId();
}
}
运行项目后,浏览器访问:http://localhost:8080/,页面显示:
1
二、自定义限定注解
如果需要根据特定的属性来指定注入的bean,则可以自定义限定注解。
1、继续使用上面例子的类 MyBean.java
2、新建一个接口 MyBeanQualifier.java
package com.example.demo;
import org.springframework.beans.factory.annotation.Qualifier;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({
ElementType.FIELD, ElementType.METHOD
}
)
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MyBeanQualifier {
String type();
}
3、修改上面例子代码 MyConfig.java
在配置bean时,需要为相应的bean设置不同的类型。
package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfig {
@Bean
@MyBeanQualifier(type = "bean1")
public MyBean bean1(){
return new MyBean("1");
}
@Bean
@MyBeanQualifier(type = "bean2")
public MyBean bean2(){
return new MyBean("2");
}
}
4、修改上面例子控制器代码 DemoController.java
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@Autowired
@MyBeanQualifier(type = "bean2")
MyBean bean;
@RequestMapping(value = "/")
public String index(){
return bean.getId();
}
}
运行项目后,浏览器访问:http://localhost:8080/,页面显示:
2
三、自定义bean的生命周期
Scope注解主要用于配置bean在容器中的生命周期,除了可以配置为singleton和prototype,在Web环境还可以配置为request、session等 值,表示容器会为一次请求或一个会话分配一个bean的实例。
如果对bean的生命周期有特殊需求,可以使用自定义的Scope。
例子:一个bean被使用3次后,就获取新的bean实例。
1、继续使用上面例子的类 MyBean.java
2、新建一个自定义的Scope类 MyScope.java
package com.example.demo;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
import java.util.HashMap;
import java.util.Map;
public class MyScope implements Scope {
//记录bean的使用次数
private Map<string> beanCounts = new HashMap<string>();
//保存实例
private Map<string> beans = new HashMap<string>();
@Override
public Object get(String s, ObjectFactory> objectFactory) {
if(beanCounts.get(s) == null){
beanCounts.put(s, 0);
}
//第一次使用,放到实例的Map中
Integer beanCount = beanCounts.get(s);
if(beanCount == 0){
Object newObject = objectFactory.getObject();
beans.put(s, newObject);
}
Object bean = beans.get(s);
//计数器加1
Integer newBeanCount = beanCount + 1;
if(newBeanCount >= 3){
newBeanCount = 0;
}
//设置新的次数
beanCounts.put(s, newBeanCount);
return bean;
}
@Override
public Object remove(String s) {
return null;
}
@Override
public void registerDestructionCallback(String s, Runnable runnable) {
}
@Override
public Object resolveContextualObject(String s) {
return null;
}
@Override
public String getConversationId() {
return null;
}
}
/<string>/<string>/<string>/<string>
3、修改上面例子代码 MyConfig.java
将自定义Scope注册到容器中。
package com.example.demo;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.CustomScopeConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import javax.annotation.PostConstruct;
@Configuration
public class MyConfig {
@Autowired
BeanFactory factory;
@PostConstruct
public void customScopeConfigurer(){
CustomScopeConfigurer config = new CustomScopeConfigurer();
config.addScope("three", new MyScope());
config.postProcessBeanFactory((ConfigurableListableBeanFactory)factory);
}
@Bean
@Scope(scopeName = "three")
public MyBean bean1(){
return new MyBean("1");
}
}
4、修改上面例子控制器代码 DemoController.java
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@Autowired
ApplicationContext ctx;
@RequestMapping(value = "/")
public String index(){
for (int i=0;i<5;i++){
System.out.println(ctx.getBean("bean1"));
}
return "";
}
}
运行项目后,浏览器访问:http://localhost:8080/,IDEA控制台输出:
com.example.demo.MyBean@61f13a02
com.example.demo.MyBean@61f13a02
com.example.demo.MyBean@61f13a02
com.example.demo.MyBean@54094334
com.example.demo.MyBean@54094334
可见前3次得到同一个bean实例。
附,项目结构图
Java架构师丨苏先生:专注于Java开发技术的研究与知识分享!
————END————
- 点赞(编辑不易,感谢您的支持)
- ...
- 转发(分享知识,传播快乐)
- ...
- 关注(每天更新Java开发技术)
- ...
閱讀更多 Java架構師丨蘇先生 的文章