Spring高级注解
目录:
1、使用限定注解;
2、自定义限定注解;
3、自定义bean的生命周期;
开发环境: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,Integer> beanCounts = new HashMap<String,Integer>(); //保存实例 private Map<String,Object> beans = new HashMap<String,Object>(); @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; } }
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实例。
附,项目结构图
相关文章
- Spring Batch 批处理框架
- 3.Spring高级话题—1.Spring Aware
- 《Spring 5 官方文档》5. 验证、数据绑定和类型转换(一)
- Is Spring Integration 5.5.10 must be based on Java 9 to use or depend on spring integration? #3761
- 面试题:Spring Boot 自动配置原理
- JAX-RS(基于Jersey) + Spring 4.x + MyBatis构建REST服务架构
- dubbo + zookeeper + spring 分布式系统(一)
- spring batch(二):核心部分(1):配置Spring batch
- Spring Boot 2.5.0 重新设计的spring.sql.init 配置有啥用?
- Spring Boot(五) 之使用配置属性
- Spring 对没有实现接口的类使用aspect的时候,可以使用CGLIB
- spring框架漏洞整理(Spring Cloud Config路径穿越导致的信息泄露)
- spring框架漏洞整理(Spring WebFlow远程代码执行)
- spring 配置文件 获取变量(PropertyPlaceholderConfigurer)
- spring事务详解(三)源码详解
- Spring之AOP实现原理
- Spring事务配置的五种方式 巨全!不看后悔,一看必懂!
- [转]Spring Boot——2分钟构建spring web mvc REST风格HelloWorld
- 【spring-bean】浅谈Spring的依赖注入(基础)
- spring boot + vue + element-ui全栈开发入门——项目部署
- Spring Boot启动过程源码分析--转
- Spring JTA multiple resource transactions in Tomcat with Atomikos example--转载
- 详解 Spring 3.0 基于 Annotation 的依赖注入实现--转载
- spring boot 让日志带上颜色