spring容器通过注解注册bean的方式
- @ComponentScan + 组件标注注解 (@Component/@Service...)
spring会将@ComponentScan(value = "com.example.demo.annotation")
com.example.demo.annotation
目录下标注了spring能识别的注解的类注册为bean
@ComponentScan
还可以指定排除和包含规则- excludeFilters: 指定排除规则,排除哪些组件
- includeFilters: 指定只需要包含哪些组件,需要设置 useDefaultFilters = false
- FilterType.ANNOTATION 基于注解过滤
- FilterType.ASSIGNABLE_TYPE : 基于给定的类型过滤
- ...
- FilterType.CUSTOM: 自定义规则过滤
其中@ComponentScan(value = "com.example.demo.annotation", /*excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}) },*/ includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Configuration.class}), @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {TestController.class}), @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class}) },useDefaultFilters = false )
CUSTOM
自定义规则中的MyTypeFilter
需要实现TypeFilter
接口,举例如下public class MyTypeFilter implements TypeFilter { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { String className = metadataReader.getClassMetadata().getClassName(); System.out.println("------>"+className); if (className.contains("er")){ return true; } return false; } }
- @Bean (可以将第三方包中的类注册为bean)
@Bean Person person() { return new Person("zhang"); }
- @Import
@Import({Color.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
- 导入一个普通类,容器会自动注册这个组件,组件的id默认是类的全类名
- 导入
ImportSelector
:返回需要注册的组件
public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{"com.example.demo.annotation.bean.Red"}; } }
- 导入
ImportBeanDefinitionRegistrar
类
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean b = registry.containsBeanDefinition("com.example.demo.annotation.bean.Color"); boolean b1 = registry.containsBeanDefinition("com.example.demo.annotation.bean.Red"); if (b && b1){ registry.registerBeanDefinition("rainBow",new RootBeanDefinition(RainBow.class)); } } }
- 使用spring提供的 FactoryBean
applicationContext.getBean("colorFactoryBean") 默认获取到的是FactoryBean调用getObject方法返回的对象public class ColorFactoryBean implements FactoryBean
{ @Override public Color getObject() throws Exception { return new Color(); } @Override public Class> getObjectType() { return Color.class; } } @Bean ColorFactoryBean colorFactoryBean() { return new ColorFactoryBean(); }
要获取FactoryBean本身,需要在id前面加个& (&colorFactoryBean)
当满足某种条件时才注册bean,使用@Conditional
举例:在windows和linux上分别注册不同的bean
@Conditional({WindowsConditional.class})
@Bean("windows")
Person person1() {
return new Person("windows");
}
@Bean("linux")
@Conditional({LinuxConditional.class})
Person person2() {
return new Person("linux");
}
public class WindowsConditional implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("os.name");
return property.toLowerCase().contains("windows");
}
}
public class LinuxConditional implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("os.name");
return property.toLowerCase().contains("linux");
}
}
bean的生命周期
spring容器管理bean的生命周期:创建--》初始化--》销毁
我们可以自定义初始化和销毁方法,容器在bean进行到当前生命周期时来调用我们自定义的初始化和销毁方法
-
创建对象:
单实例:在容器启动时创建对象
多实例:在每次获取bean的时候创建对象每个BeanPostProcessor的 postProcessBeforeInitialization 方法会在初始化之前执行
-
初始化: 对象创建好,调用初始化方法
每个BeanPostProcessor的 postProcessAfterInitialization 方法会在初始化之后执行 -
销毁:
单实例:容器关闭时销毁
多实例:容器会帮助创建这个bean,但不会管理这个bean,所以容器不会调用销毁方法,可以手动调用销毁方法
指定初始化和销毁的方法:
- 在 @Bean注解指定(initMethod = "",destroyMethod = "")
- 通过让bean实现 InitializingBean(定义初始化逻辑) 和 DisposableBean(定义销毁时逻辑)
- 使用JSR250: @PostConstruct (定义初始化逻辑) @PreDestroy(在容器销毁bean之前通知进行清理工作)
bean的后置处理器 BeanPostProcessor,其有如下两个方法,在bean的初始化前后做一些处理:
- postProcessBeforeInitialization:在初始化之前工作
- postProcessAfterInitialization:在初始化之后工作
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
private final ApplicationContext applicationContext;
public MyBeanPostProcessor(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization--->"+beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization--->"+beanName);
return bean;
}
}
如果自定义组件想要使用spring容器底层的组件(ApplicationContext,BeanFactory,***),自定义组件可以实现 ***Aware,
在创建bean的时候,相关BeanPostProcessor会调用接口规定的方法注入相关组件
例如:
如果自定义bean 实现了ApplicationContextAware 接口,在ApplicationContextAwareProcessor中会调用ApplicationContextAware的
setApplicationContext方法,注入ApplicationContext组件