全注解下的Spring
基本概念
- IoC:一种通过描述来生成或者获取对象的技术
- Bean:每一个需要管理的对象称为Spring Bean,简称Bean
- IoC的两个基本功能:
通过描述管理Bean,包括发布和获取Bean;
通过描述完成Bean之间的依赖关系
Spring Ioc容器的接口设计
- 要点:
BeanFactory是所有容器的顶级接口,因此只要实现该接口的都可以称为Spring IoC容器
ApplicationContext接口在继承上级接口的情况下,又扩展了消息国际化接口、环境可配置接口、应用事件发布接口和资源模式解析接口,所有它的功能更强大
Bean的生命周期
大致分为Bean定义、Bean的初始化、Bean的生存期、Bean的销毁
- 不完整的流程
- 完整的流程
ps:
若是没有实现ApplicaitonContext接口的容器,在Bean生命周期中,ApplicationContextAware对应的方法不会被执行;
Bean的BeanPostProcessor需要单独实现,对所有Bean都有效
常用注解
-
@Configuration
用于类上,代表这是一个Java配置文件,等价于Spring的XML配置文件 -
@Bean
常用于方法上,表示将方法返回的对象注入到Spring IoC容器中
value/name属性指明该Bean在容器中的唯一标识
(ps:若没有指明Bean的标识,则默认为方法名)
initMethod属性指明Bean初始化时执行的方法
destroyMethod属性指明Bean销毁时执行的方法 -
@Component、@Controller、@Service、@Repository
装配自己定义的Bean
value属性指定Bean的标识
(ps:若没有指明Bean的标识,则默认为类名的第一个字母小写) -
@ComponentScan
可重复注解,指明采用何种策略去扫描装配Bean
value/basePackages属性指明扫描规则
(ps:若没有指明,则默认扫描当前包及其子包)
basePackageClasses属性指定扫描的类
useDefaultFilters属性指明是否启用默认的过滤器
includeFilters属性指明仅扫描哪些
excludeFilters属性指明哪些不扫描
(ps:上述两种均需配合@Filter注解使用,该注解中的type属性用于指定类型,默认为FilterType.ANNOTATION
FilterType.ANNOTATION-按注解类型匹配,与classes属性联合使用
FilterType.ASSIGNABLE_TYPE-按给定类型匹配,与classes属性联合使用
FilterType.ASPECTJ-按ASPECTJ表达式匹配,与pattern属性联合使用,不常用
FilterType.REGEX-按正则表达式匹配,与pattern属性联合使用
FilterType.CUSTOM-按自定义类型匹配,需实现TypeFilter接口,与classes属性联合使用)
lazyInit属性指明是否延迟初始化
部分使用格式
仅扫描规则指定的(useDefaultFilters 必须改为false)
@ComponentScan(value = {""}, includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {}),
@ComponentScan.Filter(type = FilterType.ASPECTJ, pattern = {""})
}, useDefaultFilters = false)
排除规则指定的
@ComponentScan(value = {""}, excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {}),
@ComponentScan.Filter(type = FilterType.REGEX, pattern = {""})
})
可重复注解的体现
@ComponentScans(
value = {
@ComponentScan(value = {""}, includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {}),
@ComponentScan.Filter(type = FilterType.ASPECTJ, pattern = {""})
}, useDefaultFilters = false),
@ComponentScan(value = {""}, excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {}),
@ComponentScan.Filter(type = FilterType.REGEX, pattern = {""})
})
}
)
-
@Autowired
默认必须找到对应的Bean,若不确定其标注属性一定会存在并且允许这个被标注的属性为null,那么可以指定required为false
遵循的规则
字段上
首先按照by type在容器中查找,若没有,则按照by name(属性名称=Bean的标识)在容器中查找,若没有使用@Qualifier指定名称,则按by name查找时,默认为变量名
方法上
若没有使用@Qualifier指定名称,则按by name查找时,默认为setXXX后面的xXX(JavaBean属性名) -
@Qualifier
按照Bean的标识去查找,常与@Autowired注解联合使用以解决同一变量对应多个不同类型的情况(通常是父类与子类,接口与实现类,这时是同时按照名称和类型去获取) -
@Resource
javax包下,可以指定按by type或by name查找
by name
/**
* The JNDI name of the resource. For field annotations,
* the default is the field name. For method annotations,
* the default is the JavaBeans property name corresponding
* to the method. For class annotations, there is no default
* and this must be specified.
*/
String name() default "";
by type
/**
* The Java type of the resource. For field annotations,
* the default is the type of the field. For method annotations,
* the default is the type of the JavaBeans property.
* For class annotations, there is no default and this must be
* specified.
*/
Class<?> type() default java.lang.Object.class;
两者都没有,默认按by name,若没有找到,则退化成一个原始类型进行处理
-
@Primary
提升依赖注入的优先级 -
@PostConstruct
表明该方法为自定义初始化方法 -
@PreDestroy
表明该方法为自定义的销毁方法 -
@Value
既可以直接为属性赋值,又可以使用${…}占位符从x.properties属性文件中取值,也可以使用Spring EL的#{…}进行运算从而动态赋值 -
@PropertySource
value属性指定属性文件的位置
ps:
每一个属性文件需要明确的指定,不能使用通配符;
支持.properties属性文件和.xml属性文件;
常与@Value注解联合使用
/**
* Indicate the resource location(s) of the properties file to be loaded.
* <p>Both traditional and XML-based properties file formats are supported
* — for example, {@code "classpath:/com/myco/app.properties"}
* or {@code "file:/path/to/file.xml"}.
* <p>Resource location wildcards (e.g. **/*.properties) are not permitted;
* each location must evaluate to exactly one {@code .properties} resource.
* <p>${...} placeholders will be resolved against any/all property sources already
* registered with the {@code Environment}. See {@linkplain PropertySource above}
* for examples.
* <p>Each location will be added to the enclosing {@code Environment} as its own
* property source, and in the order declared.
*/
String[] value();
补充:在SpringBoot中,只需引入spring-boot-configuration-processor依赖便可以使用@Value("${…}")从applicaiton-*.properties中取值,同时还有一个特定的注解@ConfigurationProperties用于简化
- SpringBoot中特定的注解@ConfigurationProperties
prefix/value属性指定前缀(e.g. jdbc.driverClass-@ConfigurationProperties(prefix=“jdbc”))
在相应的Bean类中定义属性,属性名与prefix之后的单词一致
ps:该注解在SpringBoot源码中应用极多
/**
* The prefix of the properties that are valid to bind to this object. Synonym for
* {@link #prefix()}. A valid prefix is defined by one or more words separated with
* dots (e.g. {@code "acme.system.feature"}).
* @return the prefix of the properties to bind
*/
@AliasFor("prefix")
String value() default "";
/**
* The prefix of the properties that are valid to bind to this object. Synonym for
* {@link #value()}. A valid prefix is defined by one or more words separated with
* dots (e.g. {@code "acme.system.feature"}).
* @return the prefix of the properties to bind
*/
@AliasFor("value")
String prefix() default "";
-
@Conditional
条件装配Bean,需实现Contion接口并重写相关逻辑,只有返回true才会被装配
value属性指定实现了Condition接口的类的类型 -
@Scope
value/scopeName指明作用域的类型
/**
* Alias for {@link #scopeName}.
* @see #scopeName
*/
@AliasFor("scopeName")
String value() default "";
/**
* Specifies the name of the scope to use for the annotated component/bean.
* <p>Defaults to an empty string ({@code ""}) which implies
* {@link ConfigurableBeanFactory#SCOPE_SINGLETON SCOPE_SINGLETON}.
* @since 4.2
* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
* @see ConfigurableBeanFactory#SCOPE_SINGLETON
* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
* @see #value
*/
@AliasFor("value")
String scopeName() default "";
-
@Profile
用于快速切换环境(开发、测试、预生产(模拟生产)、生产)
Spring提供了两个参数以修改启动Profile机制,一个是spring.profiles.active,一个是spring.profiles.default,如果两个都没有,则使用该注解标注的Bean不会被装配
spring.profiles.active的优先级高于spring.profiles.default
启动Profile机制的命令为JAVA_OPTS="-Dspring.profiles.active=dev/test/pro"
在Eclipse/IDEA中,配置VM options即可
补充:在SpringBoot中还存在这样一个约定,会将"-Dspring.profiles.active"对应的值拼装为application-dev/test/pro.properties -
@ImportResource
用于导入XML形式的属性配置文件从而装配相应的Bean
/**
* Alias for {@link #locations}.
* @see #locations
* @see #reader
*/
@AliasFor("locations")
String[] value() default {};
/**
* Resource locations from which to import.
* <p>Supports resource-loading prefixes such as {@code classpath:},
* {@code file:}, etc.
* <p>Consult the Javadoc for {@link #reader} for details on how resources
* will be processed.
* @since 4.2
* @see #value
* @see #reader
*/
@AliasFor("value")
String[] locations() default {};
补充:Spring EL
-
直接读取属性配置文件的key-value为属性赋值
@Value("${…}") -
调用类的方法为属性赋值
@Value(" #{T(…).method} ")
T(…)代表引入类,…是类的全限定名 -
支持算术运算符
-
支持比较运算符
-
支持逻辑运算符
-
支持三元运算符
若有错误,请评论指出,谢谢
参考书籍
《深入浅出Spring Boot 2.x》