The spring container registers bean s through annotations
- @ComponentScan + Component annotation (@ Component/@Service...)
@ComponentScan(value = "com.example.demo.annotation")
Spring will register the classes marked with annotations recognized by spring in the com.example.demo.annotation directory as bean s
@ComponentScan can also specify exclusion and inclusion rules- excludeFilters: specify exclusion rules and which components to exclude
- includeFilters: specify which components only need to be included. useDefaultFilters = false should be set
- FilterType.ANNOTATION filtering based on annotations
- FilterType.ASSIGNABLE_TYPE: filter based on the given type
- ...
- FilterType.CUSTOM: custom filtering rules
@ComponentScan(value = "com.example.demo.annotation", /*excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = ) },*/ includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = ), @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = ), @ComponentScan.Filter(type = FilterType.CUSTOM,classes = ) },useDefaultFilters = false )
MyTypeFilter in CUSTOM custom rule needs to implement TypeFilter interface, for example: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 (classes in third-party packages can be registered as beans)
@Bean Person person() { return new Person("zhang"); }
- @Import
@Import()
- When you import a common class, the container will automatically register the component. The component id is the full class name of the class by default
- Import ImportSelector: returns the components that need to be registered
public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{"com.example.demo.annotation.bean.Red"}; } }
- Import ImportBeanDefinitionRegistrar class
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)); } } }
- Use the FactoryBean provided by spring
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(); }
applicationContext.getBean("colorFactoryBean") obtains the object returned by the FactoryBean calling the getObject method by default
To get the FactoryBean itself, you need to add & (& colorfactorybean) before the id
Register bean s only when certain conditions are met, using @ Conditional
Example: register different bean s on windows and linux respectively
@Conditional() @Bean("windows") Person person1() { return new Person("windows"); } @Bean("linux") @Conditional() 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"); } }
The lifecycle of a bean
The life cycle of spring container managed bean s: create -- initialize -- destroyWe can customize the initialization and destruction methods, and the container will call our customized initialization and destruction methods when the bean reaches the current life cycle
-
Create object:
Single instance: creates an object when the container starts
Multi instance: create an object every time you get a beanThe postProcessBeforeInitialization method of each BeanPostProcessor is executed before initialization
-
Initialization: after the object is created, call the initialization method
The postProcessAfterInitialization method of each BeanPostProcessor is executed after initialization -
Destruction:
Single instance: destroy when container is closed
Multi instance: the container will help create this bean, but it will not manage this bean, so the container will not call the destruction method, and you can call the destruction method manually
- Specify in @ Bean annotation (initmethod = '', destroymethod = '')
- By letting the bean implement InitializingBean (defining initialization logic) and DisposableBean (defining destruction logic)
- Use JSR250: @PostConstruct (define initialization logic) @ PreDestroy (notify the container to clean up before destroying bean s)
The bean post processor, BeanPostProcessor, has the following two methods to do some processing before and after bean initialization:
- postProcessBeforeInitialization: works before initialization
- postProcessAfterInitialization: works after initialization
@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; } }
If the custom component wants to use the components at the bottom of the spring container (ApplicationContext, BeanFactory, * * *), the custom component can implement * * * Aware,
When creating a bean, the relevant BeanPostProcessor will call the methods specified in the interface to inject relevant components
For example:
If the custom bean implements the ApplicationContextAware interface, the ApplicationContextAware interface will be called in the ApplicationContextAware processor
setApplicationContext method, inject ApplicationContext component