Spring component registration
@Configuration
@The Configuration annotation tells Spring that this is a Configuration class
@Bean
@Bean annotation is to register a bean in the container. The type is the type of return value. The default id is the method name as the id
@Bean("person") public Person person2(){ System.out.println("create a new bean of person"); return new Person(); }
@ComponentScan
@ComponentScan(value = "com.eric",excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class})
@Properties of ComponentScan
- value: Specifies the package to scan
- excludeFilters = Filter []: specifies which components are excluded according to what rules during scanning
- includeFilters = Filter []: specifies which components only need to be included during scanning
/** * Description: spring-parent * Configuration class = = configuration file * * @author caoqianqian * @date 2021/2/14 */ @Configuration //Tell Spring that this is a configuration class @ComponentScan(value = "com.eric",excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class}) }) public class MainConfig { //Register a Bean in the container. The type is the type of return value. The default id is the method name as the id @Bean public Person person(){ return new Person("testName",20); } }
@Scope
The Scope of the bean is defined through the @ Scope annotation, which can also be said to adjust the Scope. The components loaded in the ioc container are single instance by default.
Scope range is the value range of value
- prototype multi instance: when the ioc container is started, it will not call the method to create the object. It will be placed in the container. The method will be called to create the object every time it is obtained.
- singleton single instance (default):
When the ioc container starts, it will call the method to create the object and put it into the ioc container. In the future, each acquisition is taken from the container (map.get()) - Request create an instance for the same request
- Session create an instance of the same session
//Use the @ Scope annotation to set the Scope of the bean, or adjust the Scope @Scope("singleton") @Bean("person") public Person person() { System.out.println("I'm creating an instance Person"); return new Person("Person", 28); }
@Lazy load
Single instance bean: the object is created by default when the container is started.
Lazy loading: the container does not create an object at startup. The object is created and initialized when the bean is used (obtained) for the first time.
After a single instance bean is annotated with lazy loading, the container does not create an object when it is started. The object will be created and initialized when it is used for the first time.
@Bean("person") @Lazy public Person person2(){ System.out.println("create a new bean of person"); return new Person(); }
@Conditional
@Conditional judges according to certain conditions, and registers bean s in the container if the conditions are met
It is marked on the method, which means that the method will take effect only if it meets certain conditions.
It is marked on the class, and the components in the class are set uniformly, indicating that all bean registrations configured in this class will take effect only if the current conditions are met
Determine whether it is a Linux system
public class LinuxCondition implements Condition { /** *Determine whether it is a Linux system * @param conditionContext Determine the context (environment) that the condition can use * @param annotatedTypeMetadata Annotation information of the current annotation * @return */ @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { //beanFactory used by ioc can be obtained ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory(); //Get class loader ClassLoader classLoader = conditionContext.getClassLoader(); //Get current environment information Environment environment = conditionContext.getEnvironment(); //Get the bean defined registration class BeanDefinitionRegistry registry = conditionContext.getRegistry(); //Determine the registration of bean s in the container boolean definition = registry.containsBeanDefinition("person"); RootBeanDefinition beanDefinition = new RootBeanDefinition(Person.class); //Register bean s in container registry.registerBeanDefinition("person2",beanDefinition); String property = environment.getProperty("os.name"); if(property.contains("linux")){ return true; } return false; } }
Determine whether it is a Windows system
public class WindowsCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { Environment environment = conditionContext.getEnvironment(); String osName = environment.getProperty("os.name"); if (osName.contains("Windows")){ return true; } return false; } }
Configuration class
@Configuration public class MainConfig2 { /** *Conditional({Condition}):Judge according to certain conditions and register bean s in the container if the conditions are met * If the system is windows, register ("bill") in the container * If the system is linux, register ("linus") in the container * @return */ @Conditional({WindowsCondition.class}) @Bean("bill") public Person person(){ return new Person("Bill Gates",62); } @Conditional({LinuxCondition.class}) @Bean("linus") public Person person2(){ return new Person("linus",42); } @Bean public ColorFactoryBean colorFactoryBean(){ return new ColorFactoryBean(); } }
test method
@Test public void testCondition() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig2.class); ConfigurableEnvironment environment = ac.getEnvironment(); String[] beanNamesForType = ac.getBeanNamesForType(Person.class); //Get the value of environment variable dynamically: windows 7 String property = environment.getProperty("os.name"); System.out.println(property); for (String p:beanNamesForType) { System.out.println(p); } }
The running results are as follows: the system of Windows 7, so bill is registered
Windows 7 bill person2
@Import
Quickly import components. By default, the id is the full class name of the component
The @ Import annotation is added to the configuration class
@Configuration @Import({Color.class, Dog.class}) public class MainConfig2 { /** *Conditional({Condition}):Judge according to certain conditions and register bean s in the container if the conditions are met * If the system is windows, register ("bill") in the container * If the system is linux, register ("linus") in the container * @return */ @Conditional({WindowsCondition.class}) @Bean("bill") public Person person(){ return new Person("Bill Gates",62); } @Conditional({LinuxCondition.class}) @Bean("linus") public Person person2(){ return new Person("linus",22); } }
test method
@Test public void testImport() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig2.class); String[] beanNamesForType = ac.getBeanDefinitionNames(); for (String p:beanNamesForType) { System.out.println(p); } }
Running result: in addition to the internal bean, Color and Dog are also registered
org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory mainConfig2 com.eric.bean.Color com.eric.bean.Dog bill person2
@Import use ImportSelector
//Custom logic returns the components to be imported public class MyImportSelector implements ImportSelector { //The return value is the full class name of the component imported into the container //AnnotationMetadata currently annotates all annotation information of the @ Import annotation class @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { Set<String> annotationTypes = annotationMetadata.getAnnotationTypes(); for(String str : annotationTypes){ System.out.println("===="+str); } return new String[]{"com.eric.bean.Blue","com.eric.bean.Red"}; } }
@Import annotation plus custom component MyImportSelector
@Configuration @Import({Color.class, Dog.class,MyImportSelector.class}) public class MainConfig2 { /** *Conditional({Condition}):Judge according to certain conditions and register bean s in the container if the conditions are met * If the system is windows, register ("bill") in the container * If the system is linux, register ("linus") in the container * @return */ @Conditional({WindowsCondition.class}) @Bean("bill") public Person person(){ return new Person("Bill Gates",62); } @Conditional({LinuxCondition.class}) @Bean("linus") public Person person2(){ return new Person("linus",22); } }
test method
@Test public void testImport() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig2.class); String[] beanNamesForType = ac.getBeanDefinitionNames(); for (String p:beanNamesForType) { System.out.println(p); } }
Running result: blue red has been registered
====org.springframework.context.annotation.Configuration ====org.springframework.context.annotation.Import org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory mainConfig2 com.eric.bean.Color com.eric.bean.Dog com.eric.bean.Blue com.eric.bean.Red bill person2
@Import uses ImportBeanDefinitionRegistrar
Manually register bean s into the container
//bean to be registered public class Rainbow { }
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /** * * @param importingClassMetadata Annotation information of the current class * @param registry BeanDefinition Registration class * Add all the bean s that need to be added to the container and call * BeanDefinitionRegistry.registerBeanDefinition Register manually */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean blueDefinition = registry.containsBeanDefinition("com.eric.bean.Blue"); if (blueDefinition){ //Specifies the definition information of the bean RootBeanDefinition beanDefinition = new RootBeanDefinition(Rainbow.class); //Register a bean and specify the bean name registry.registerBeanDefinition("rainbow", beanDefinition); } } }
Configuration class: @ Import added MyImportBeanDefinitionRegistrar in
@Configuration @Import({Color.class, Blue.class,MyImportBeanDefinitionRegistrar.class}) public class MainConfig2 { }
Test method:
@Test public void testImport() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig2.class); String[] beanNamesForType = ac.getBeanDefinitionNames(); for (String p:beanNamesForType) { System.out.println(p); } }
Running result: the logic judges that Blue exists, so rainbow is registered
mainConfig2 com.eric.bean.Blue bill person2 rainbow
Registering components using FactoryBean
Use the FactoryBean provided by spring
Create a ColorFactoryBean to implement the FactoryBean interface:
//Create a Spring defined FactoryBean public class ColorFactoryBean implements FactoryBean<Color> { /** * Returns a Color object that will be added to the container * @return * @throws Exception */ @Override public Color getObject() throws Exception { System.out.println("ColorFactoryBean=========getObject====="); return new Color(); } /** * Returned bean type * @return */ @Override public Class<Color> getObjectType() { return Color.class; } /** * Single case or not * Returning true means that it is a single instance and a copy is saved in the container * false It is multi instance, and a new bean will be created each time * @return */ @Override public boolean isSingleton() { return true; } }
Register the factory bean in the configuration class
@Configuration public class MainConfig2 { @Bean public ColorFactoryBean colorFactoryBean(){ return new ColorFactoryBean(); } }
Test method:
@Test public void testFactoryBean() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig2.class); //The factory bean gets the object created by calling the getObject() method Object bean1 = ac.getBean("colorFactoryBean"); Object bean2 = ac.getBean("colorFactoryBean"); System.out.println("bean Type of:"+bean1.getClass()); //Single instance returns true and multiple instances return false System.out.println(bean1 == bean2); //By default, the object created by the factory bean calling getObejct is obtained //To get the factory bean itself, we need to prefix the id with an & id Object bean3 = ac.getBean("&colorFactoryBean"); System.out.println("bean3 Type of:"+bean3.getClass()); }
Running result: the single instance obtains the same bean, and the bean obtained after adding & is ColorFactoryBean
ColorFactoryBean=========getObject===== bean Type of: class com.eric.bean.Color true bean3 Type of: class com.eric.condition.ColorFactoryBean
summary
To register components in a container:
- Package scanning + Component annotation (@ Controller/@Service/@Repository/@Component)
- @Components in the third-party package imported by Bean
- @Import quickly imports a component into the container
- @Import (component to be imported into the container): this component will be automatically registered in the container, and the id is the full class name by default
- @ImportSelector returns an array of the full class names of the components to be imported
- @ImportBeanDefinitionRegistrar manually registers beans into the container
- Use the FactoryBean provided by Spring
- By default, the object created by the factory bean calling the getObject method is obtained
- To get the factory Bean itself, we need to add an id in front of it&
ok, the component registration is completed and the flowers are scattered.