spring注解
Posted 新火且试茶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring注解相关的知识,希望对你有一定的参考价值。
一、组件注册
1、@Configuration和@Bean
- @Configuration:告诉spring这是一个配置类。配置类==配置文件,可使用注解在这个类中进行配置文件中的配置。
- @Bean:给容器中注册一个Bean,类型为返回值类型,id默认使用方法名为id。可修改
- 使用AnnotationConfigApplicationContext来从容器中读取bean。
2、@ComponentScan
与.xml配置文件中的扫描包相同。
1)、属性:
value:要扫描的包
excludeFilters=Filter[]:指定扫描的时候按照什么规则排除哪些组件
includeFilters=Filter[]:指定扫描的时候只需要那些组件。需要将默认过滤关闭useDefaultFilters = false才有用,否则全部都会被导入。
//将com.atguigu包及其子包下的有@Controller和@Service的组件添加到容器中,
@Configuration@ComponentScan(value = "com.atguigu" , includeFilters = {@Filter(type = FilterType.ANNOTATION,classes = {Controller.class,Service.class})}, useDefaultFilters = false)public class MainConfig {
@ComponentScan是可重复注释,可以扫描多个包,或者用@ComponentScans来配置多个@ComponentScan
2)、TypeFilter指定过滤规则
-
ANNOTATION 按照注释
-
ASSIGNABLE_TYPE 按照给定的类型
-
REGEX 正则表达式
-
CUSTOM 自定义规则。
自定义过滤规则
实现TypeFilter接口
public class MyTypeFilter implements TypeFilter {
/**
* metadataReader:读取当前正在扫描的类
* metadataReaderFactory:可以获取到任何类的信息
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
//获取当前正在扫描类的注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata(); //获取当前类资源
Resource resource = metadataReader.getResource();
if(classMetadata.getClassName().contains("er")) {//将类名带有er的扫描进容器
return true;
}
return false;
}
}
3、@Scope设置组件作用域
相当于bean标签中的scope属性
- prototype:多实例。每次获取时才会调用方法,并且每一次获取都会调用一次
- singleton:单实例的。(默认值):ioc容器启动时就会调用方法创建对象放到ioc容器中,以后每次获取就是直接从容器中拿
- request:同一次请求创建一个实例
- session:同一个session创建一个实例
4、@Lazy (bean懒加载)
只针对单例而言。
单例bean,默认在容器启动时创建对象
使用懒加载,在第一次获取时创建实例
5、@Conditional(按条件判断注册)
public @interface Conditional {
/**
* All {@link Condition Conditions} that must {@linkplain Condition#matches match}
* in order for the component to be registered.
*/
Class<? extends Condition>[] value();
}
参数类型为Class数组,可通过实现Condition接口的类来进行条件判断
满足当前条件,配置的bean才能生效。放在类上,可以对类中的组件统一设置
例:在linux环境下才注册一个bean
//作为条件要实现Condition接口
public class LinuxCondition implements Condition {
/**
* ConditionContext:判断条件能使用的上下文环境
* AnnotatedTypeMetadata:注释信息
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
if(property.equals("Linux")) {
return true;
}
return false;
}
}
使用
@Conditional({LinuxCondition.class})
@Bean("linux")
public Person person3() {
return new Person("linus",50);
}
6、@Import
1)、快速给容器中导入一个组件。
id默认为全类名。
@Import(要导入容器的组件)。容器就会自动注册这个组件,默认id为全类名。
2)、实现自定义逻辑返回需要的组件
1. importSelector:返回要导入组件的全类名数组。
创建一个实现了接口ImportSelector的类,实现方法selectImports方法,可以在内部书写自定义的逻辑,返回的数组要是全类名,并且不能为空指针,最低为空数组。
public class MyImportSelect implements ImportSelector{
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.atguigu.bean.Blue","com.atguigu.bean.Red"};
}
}
@Import({Color.class,MyImportSelect.class})
在导入这个实现类时就会将自定义的组件({"com.atguigu.bean.Blue","com.atguigu.bean.Red"})导入容器中,而不是将实现类导入容器中。
2. ImportBeanDefinitionRegistrar接口
与ImportSelector功能相同,可以将要添加的组件注册到容器中
7、FactoryBean注册组件
工厂Bean获取的是调用getObject创建的对象
创建一个实现了FactoryBean接口的类
public class ColorFactoryBean implements FactoryBean<Color> {
@Override
public Color getObject() throws Exception {
return new Color();
}
@Override
public Class<?> getObjectType() {
return Color.class;
}
@Override
public boolean isSingleton() {
// TODO Auto-generated method stub
return FactoryBean.super.isSingleton();
}
}
-
getObejct:返回一个对象,这个对象会添加到容器中
-
getObjectType:返回对象的类型
-
isSingleton:是否是单例
配置Bean
@Bean
public ColorFactoryBean colorFactoryBean() {
return new ColorFactoryBean();
}
测试FactoryBean,结果为Color。若通过id获取bean时在id前加上&符,那么变回获取工厂本身,或者通过类型获取
@Test
public void testFactoryBean() {
Object bean = ioc.getBean("colorFactoryBean");
System.out.println(bean.getClass());
}//获取到Color
@Test
public void testFactoryBean() {
Object bean = ioc.getBean("&colorFactoryBean");
System.out.println(bean.getClass());
}//获取到ColorFactoryBean
二、生命周期(指定初始化和销毁方法)
1、@Bean指定初始化和销毁方法
默认由容器来管理bean的声明周期。但我们可以自定义初始化和销毁方法,容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。
- 指定初始化和销毁方法。像bean标签里的init-method和destroy-method方法。
- 在Bean注解中对应有initMethod方法和destroyMethod方法
- 初始化:对象创建完成并且属性赋值完毕。销毁:容器关闭。
- 多实例:容器不会管理这个bean。不会调用其销毁方法
2、InitializingBean和DisposableBean接口
通过让bean实现InitializingBean和DisposableBean接口同样可以指定初始化和销毁方法
3、@PostConstruct和@PreDestroy
通过@PostConstruct和@PreDestroy可以实现同样效果。将两个注释分别标注在bean方法的初始化、销毁方法。
-
@PostConstruct:在创建bean并为属性赋值后调用该注解标注的方法
-
@PreDestroy:在容器关闭之前调用该注解标注的方法
4、BeanPostProcessor
bean的后置处理器
在bean初始化前后进行一些处理工作:
-
postProcessorBeforeInitialization:在初始化之前工作
-
postProcessAfterInitializeation:在初始化之后工作
三、属性赋值
1、@Value
- 基本数值
- 可以写SpEL,#{}取出
- 可以写${},取出配置文件中的值
2、@PropertySource
加载外部配置文件,与xml中的加载外部属性文件功能相同
四、自动装配
自动装配:spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值。
1、Autowired(Spring定义的)
自动注入。
- 默认优先按照类型从容器中找对应的组件
- 如果找到多个相同类型的组件,在将属性的名称作为id到容器中查找
- @Qualifier(),使用@Qualifier指定要装配的组件id,而不是使用属性
- 默认一定要将属性赋值好,没有就会报错。可以使用属性required,来指定是否必须要被装配
- @Primary,让spring进行自动装配的时候,在未指定装配的情况下,默认使用此注解标注的bean作为装配的首选项。若使用了@Qualifier,那么便使用@Qualifier指定的bean的名字
2、@Resource和@Inject(java规范)
- @Resource:可以和@Autowired一样实现自动装配功能,默认使用属性的名称装配。不能支持@Primary和requred功能
- @Inject:需要导入javax.inject的包,和@Autowired的功能一样。但是没有required=false的功能。
3、方法、构造器位置的自动装配
1.标注在方法上
spring容器创建当前对象,就会调用方法,完成赋值
方法使用的参数,自定义类型的值从ioc容器获取。
默认加载ioc容器中的组件,容器启动会自动调用无参构造器创建对象,再进行初始化等操作
2.标注在构造方法上
如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取
3.标注在参数上
4.@Bean标注的方法创建对象的时候,方法参数的值从容器中获取。默认不写@Autowired
5.都是从ioc容器中获取参数的值
4.、自定义组件注入底层组件
自定义组件想要使用spring容器底层的一些组件(ApplicationContext、BeanFactory)
自定义组件实现xxxAware:在创建对象的时候,会调用接口规定的方法注入相关组件。
5、@Profile环境搭建
Profile:Spring为我们提供的可以根据当前环境,动态的激活和切换一些列组件的功能
- 加了环境标识的bean,只有这个环境被激活的时候才能够注册到容器中,默认是default环境
- 写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
- 没有标注环境的bean,在所有的环境下都被加载
开发环境,测试环境,生产环境
@Porfile根据环境注册bean
1.使用命令行动态参数:在虚拟机参数位置加载-Dspring.profiles.actice=test
切换到测试环境
2.使用代码的方式激活某些环境
@Test
public void test01() {
//1.创建一个无参的ApplicationContext
AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext();
//2.设置需要激活的环境
ioc.getEnvironment().setActiveProfiles("test","prod");
//3.注册主配置类
ioc.register(MainConfigOfProfile.class);
//4.启动刷新容器
ioc.refresh();
String[] beanDefinitionNames = ioc.getBeanDefinitionNames();
for (String name : beanDefinitionNames) {
System.out.println(name);
}
}
以上是关于spring注解的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot实战笔记-- Spring高级话题(组合注解与元注解)