Spring component registration

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:

  1. Package scanning + Component annotation (@ Controller/@Service/@Repository/@Component)
  2. @Components in the third-party package imported by Bean
  3. @Import quickly imports a component into the container
    1. @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
    2. @ImportSelector returns an array of the full class names of the components to be imported
    3. @ImportBeanDefinitionRegistrar manually registers beans into the container
  4. Use the FactoryBean provided by Spring
    1. By default, the object created by the factory bean calling the getObject method is obtained
    2. 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.

Tags: Java Javascript Spring

Posted by bagnallc on Tue, 19 Apr 2022 03:32:29 +0930