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<Color> { @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元件