spring series - annotation driven principle and source code - bean component registration

catalogue

1, Environment initialization

1. Environmental preparation

2, Manual injection of bean s

1. xml injection bean

2. Inject beans in @ configuration & @ bean mode

3, Automatically scan registered components and bean s

1. Scan packages using xml

2. Scan with @ ComponentScan

3. Exclusion of packet scanning

4, Other annotations for component registration

1. Use @ Scope - to set component Scope

2. @ lazy bean lazy load

3. @ Conditional - register bean s according to conditions

5, Use @ Import to quickly Import a component into the container

1. @ Import import Import components

2. Use ImportSelector to import bean s

3. Use ImportBeanDefinitionRegistrar to import beans

6, Create a bean using FactoryBean

1. Create a bean using FactoryBean

7, bean component registration summary

Friendly tips: this series of documents is not suitable for students with zero foundation of springboot~

1, Environment initialization

1. Environmental preparation

(1) Create a new maven project.

(2) pom imports packages related to spring beans and junit tests

<!--introduce spring-bean Related packages-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.12.RELEASE</version>
</dependency>
<!--junit test-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

(3) The environment package is as follows

 

2, Manual injection of bean s

1. xml injection bean

(1) Define the Person class

package com.xiang.spring.bean;

public class Person {

    private String name;
    private Integer age;

        ......get set toString......
}

(2) Create the beans.xml configuration file in the resources directory

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--use xml to configure bean-->
    <bean id="person" class="com.xiang.spring.bean.Person">
        <property name="age" value="18"></property>
        <property name="name" value="lisi"></property>
    </bean>
</beans>

(3) Create the main method to get the bean in ioc

package com.xiang.spring;

import com.xiang.spring.bean.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTest {

    public static void main(String[] args) {

        // Use the xml configuration file to get the bean s in the container
        ApplicationContext applicationContextXml = new ClassPathXmlApplicationContext("beans.xml");
        Person xmlPerson = (Person) applicationContextXml.getBean("person");
        System.out.println(xmlPerson);
    }
}

2. Inject beans in @ configuration & @ bean mode

(1) Define the Person class

ditto

(2) Create configuration class

package com.xiang.spring.config;

import com.xiang.spring.bean.Person;
import org.springframework.context.annotation.Bean;

// Tell spring that this is a configuration class
@Configuration
public class MainConfig {

    /**
     * Register a bean in the container. The type is the type of return value. By default, the method name is used as the id name
     * Use @ Bean("person") to specify a name for a bean instead of a method name
     */
    //@Bean
    @Bean("person")
    public Person person01() {
        return new Person("zhangsan", 20);
    }

}

(3) Create the main method to get the bean in ioc

package com.xiang.spring;

import com.xiang.spring.bean.Person;
import com.xiang.spring.config.MainConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTest {

    public static void main(String[] args) {

        // Use the xml configuration file to get the bean s in the container
        ApplicationContext applicationContextXml = new ClassPathXmlApplicationContext("beans.xml");
        Person xmlPerson = (Person) applicationContextXml.getBean("person");
        System.out.println(xmlPerson);
        System.out.println("------------------------");
        // Create an IOC container, load the configuration class, and get the Person in the container
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        // There are many ways to get the bean s in the container
        Person bean = applicationContext.getBean(Person.class);
        Person bean2 = applicationContext.getBean("person", Person.class);
        System.out.println(bean);
        System.out.println(bean2);
        // Gets the name of the bean of the specified class type (the default is the method name of the bean)
        String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class);
        for (String s : beanNamesForType) {
            System.out.println(s);
        }
    }
}

// Operation results
Person{name='lisi', age=18}
------------------------
Person{name='zhangsan', age=20}
Person{name='zhangsan', age=20}
person

3, Automatically scan registered components and bean s

1. Scan packages using xml

(1) Add the following to beans.xml

<!--Package scanning, as long as it is marked@Controller,@Service,@Repository,@Component of bean Will be created into the container-->
<!--use-default-filters Disable the default rule before you can continue to set the scan filter rule-->
<context:component-scan base-package="com.xiang.spring" use-default-filters="false"></context:component-scan>

2. Scan with @ ComponentScan

(1) Define Controller, Service and Dao classes

package com.xiang.spring.controller;
import org.springframework.stereotype.Controller;
@Controller
public class BookController {
}

package com.xiang.spring.service;
import org.springframework.stereotype.Service;
@Service
public class BookService {
}

package com.xiang.spring.dao;
import org.springframework.stereotype.Repository;
@Repository
public class BookDao {
}

(2) Set configuration class

package com.xiang.spring.config;


import com.xiang.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;


// Tell spring that this is a configuration class
@Configuration
@ComponentScan(value = "com.xiang.spring")
public class MainConfig {

    /**
     * Register a bean in the container. The type is the type of return value. By default, the method name is used as the id name
     * Use @ Bean("person") to specify a name for a bean instead of a method name
     */
    //@Bean
    @Bean("person")
    public Person person01() {
        return new Person("zhangsan", 20);
    }
}

(3) Write the test class to get all the registered bean s in the ioc container

package com.xiang.spring.test;

import com.xiang.spring.config.MainConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class IOCTest {

    @Test
    public void test01(){
        // Get IOC container
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        // Gets the names of all bean s in the container
        String[] definitionNames = applicationContext.getBeanDefinitionNames();
        for (String definitionName : definitionNames) {
            System.out.println(definitionName);
        }
    }
}

// Operation results
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookDao
bookService
person

3. Exclusion of packet scanning

(1) excludeFilters excludes components that need to be scanned

Modify configuration class

package com.xiang.spring.config;

import com.xiang.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

// Tell spring that this is a configuration class
@Configuration
/**
* During package scanning, bean s marked with @ Controller, @ Service, @ Repository, @ Component will be created into the container
* @ComponentScan : value: Specify the package to scan;
*                   excludeFilters = Filter[]: Specify which components are excluded according to what rules during scanning
*                   includeFilters = Filter[]: Specify which components to include during scanning, and add useDefaultFilters = false
*      jdk8 Multiple @ ComponentScan can be written above, or @ ComponentScans = {@ComponentScan} can be used to specify multiple scanned packages for non jdk8 above
*/
@ComponentScan(value = "com.xiang.spring", excludeFilters = {
        @Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class}) // Exclude Controller and Service according to comments
})
public class MainConfig {

    /**
     * Register a bean in the container. The type is the type of return value. By default, the method name is used as the id name
     * Use @ Bean("person") to specify a name for a bean instead of a method name
     */
    //@Bean
    @Bean("person")
    public Person person01() {
        return new Person("zhangsan", 20);
    }
}


// Operation results
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookDao
person

(2) includeFilters only need to include which components

Modify configuration class

package com.xiang.spring.config;

import com.xiang.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

// Tell spring that this is a configuration class
@Configuration
/**
* During package scanning, bean s marked with @ Controller, @ Service, @ Repository, @ Component will be created into the container
* @ComponentScan : value: Specify the package to scan;
*                   excludeFilters = Filter[]: Specify which components are excluded according to what rules during scanning
*                   includeFilters = Filter[]: Specify which components to include during scanning, and add useDefaultFilters = false
*      jdk8 Multiple @ ComponentScan can be written above, or @ ComponentScans = {@ComponentScan} can be used to specify multiple scanned packages for non jdk8 above
*/
@ComponentScan(value = "com.xiang.spring", includeFilters = {
        @Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class}) // Which components need to be included: Controller and Service
}, useDefaultFilters = false)
public class MainConfig {

    /**
     * Register a bean in the container. The type is the type of return value. By default, the method name is used as the id name
     * Use @ Bean("person") to specify a name for a bean instead of a method name
     */
    //@Bean
    @Bean("person")
    public Person person01() {
        return new Person("zhangsan", 20);
    }
}

// Operation results
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookService
person

(3) Detailed explanation of enumeration types excluded by package scanning

public enum FilterType {
    ANNOTATION, // annotation type 
    ASSIGNABLE_TYPE, // According to the specified type
    ASPECTJ, // According to the expression of Aspectj, it is basically not used
    REGEX, // According to regular expression
    CUSTOM; // Custom rules

    private FilterType() {
    }
}

(4) Exclude by specified type

Configure in the configuration class:

@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = BookService.class) // Exclusion rule, only BookService will exclude

(5) Custom exclusion rules

①   Write filter rule class

package com.xiang.spring.config;

import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;

/**
* Custom package scan exclusion rule class
*/
public class MyTypeFilter implements TypeFilter {

    /**
     * MetadataReader : Read the information of the class currently being scanned
     * MetadataReaderFactory: You can get the information of any other class
     */
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        // Gets the information of the current class annotation
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        // Gets the class information of the class currently being scanned
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        // Gets the resource (classpath) of the current class
        Resource resource = metadataReader.getResource();

        String className = classMetadata.getClassName();
        System.out.println("----->" + className);

        if(className.contains("er")){
            return true;
        }
        // Return true to match successfully; Return false to end the match
        return false;
    }
}

②   Set custom filter rules in configuration class

// Tell spring that this is a configuration class
@Configuration
@ComponentScan(value = "com.xiang.spring", includeFilters = {
        @Filter(type = FilterType.CUSTOM, classes = MyTypeFilter.class) // Custom filter rule
}, useDefaultFilters = false)
public class MainConfig {

③   Execute the test class to view the results

package com.xiang.spring.test;

import com.xiang.spring.config.MainConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class IOCTest {

    @Test
    public void test01(){
        // Get IOC container
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        // Gets the names of all bean s in the container
        String[] definitionNames = applicationContext.getBeanDefinitionNames();
        for (String definitionName : definitionNames) {
            System.out.println(definitionName);
        }
    }
}

// Print results
----->com.xiang.spring.test.IOCTest
----->com.xiang.spring.bean.Person
----->com.xiang.spring.config.MyTypeFilter
----->com.xiang.spring.controller.BookController
----->com.xiang.spring.dao.BookDao
----->com.xiang.spring.MainTest
----->com.xiang.spring.service.BookService
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person
myTypeFilter
bookController
bookService

4, Other annotations for component registration

1. Use @ Scope - to set component Scope

(1) Define configuration class

package com.xiang.spring.config;

import com.xiang.spring.bean.Person;
import org.springframework.context.annotation.*;
import org.springframework.context.annotation.ComponentScan.Filter;

@Configuration
public class MainConfig2 {

    /**
     *  The default is single instance. There are four configuration methods (taken from the comment of @ Scope's value)
     * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
     * @see ConfigurableBeanFactory#SCOPE_SINGLETON
     * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
     * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
     *
     * Resolution:
     *  prototype: Multi instance: the ioc container will not call the method to create the object when it is started. The method will be called to create the object every time it is obtained, and the method will be called to obtain 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, it will be taken directly from the container every time.
     *  request: Create one instance at a time (web environment is available, but not commonly used)
     *  session: Create an instance of the same session (web environment is available, but not commonly used)
     */
    @Scope("prototype")
    @Bean("person2")
    public Person person() {
        System.out.println("Add to container Person......");
        return new Person("zhangsan", 22);
    }
}

(2) Writing test methods

@Test
public void test02(){
    // Get IOC container
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    // The default is single instance
    Object obj1 = applicationContext.getBean("person2");
    Object obj2 = applicationContext.getBean("person2");
    System.out.println(obj1 == obj2);
}

// Operation results
 Add to container Person......
Add to container Person......
false

2. @ lazy bean lazy load

(1) Add @ Lazy annotation to bean

/**
* 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.
*
*/
@Lazy
@Bean("person2")
public Person person() {
    System.out.println("Add to container Person......");
    return new Person("zhangsan", 22);
}

(2) Writing test methods

@Test
public void test02(){
    // Get IOC container
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    // The default is single instance
    System.out.println("--------------");
    Object obj1 = applicationContext.getBean("person2");
}

// Output results
--------------
Add to container Person......

3. @ Conditional - register bean s according to conditions

(1) Write two conditions

package com.xiang.spring.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
// Determine whether it is a windows system
public class WindowsCondition implements Condition {
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // Access to environmental information
        Environment environment = context.getEnvironment();
        // Get operating system
        String osName = environment.getProperty("os.name");
        if(osName.contains("Windows")){
            return true;
        }
        return false;
    }
}

package com.xiang.spring.condition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
// Determine whether it is a linux system
public class LinuxCondition implements Condition {
    /**
     * ConditionContext: Determine the context in which the condition can be used
     * AnnotatedTypeMetadata: The comment information of @ Conditional is currently marked
     */
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // beanFactory factory used by ioc can be obtained
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        // Can get class loader
        ClassLoader classLoader = context.getClassLoader();
        // Access to environmental information
        Environment environment = context.getEnvironment();
        // Get the bean defined registration class
        BeanDefinitionRegistry registry = context.getRegistry();
        // You can determine whether the container contains the definition of beans, or you can register beans in the container
        registry.containsBeanDefinition("person");
        // Get operating system
        String osName = environment.getProperty("os.name");
        if(osName.contains("linux")){
            return true;
        }
        return false;
    }
}

(2) Add bean to configuration class

/**
* @Conditional({}): Judge according to certain conditions and register bean s in the container if the conditions are met
* It can be set uniformly on methods or classes
*/
@Conditional({LinuxCondition.class})
@Bean
public Person linux() {
    return new Person("linux", 60);
}
@Conditional({WindowsCondition.class})
@Bean
public Person windows() {
    return new Person("windows", 50);
}

(3) Test method test

@Test
public void test03(){
    // Get IOC container
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    ConfigurableEnvironment environment = applicationContext.getEnvironment();
    System.out.println("Current operating environment" + environment.getProperty("os.name"));
    Map<String, Person> beansOfType = applicationContext.getBeansOfType(Person.class);
    System.out.println(beansOfType);
}

// Operation results
 Current operating environment Windows 10
{windows=Person{name='windows', age=50}}

5, Use @ Import to quickly Import a component into the container

1. @ Import import Import components

(1) New class

public class Color {
}

public class Red {
}

(2) Add annotation on configuration class

@Configuration
// When importing a component, the id is the full class name of the component by default
@Import({Color.class, Red.class})
public class MainConfig2 {

(3) Test method test

@Test
public void test04(){
    // Get IOC container
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    String[] definitionNames = applicationContext.getBeanDefinitionNames();
    for (String name : definitionNames) {
        System.out.println(name);
    }
}

// Operation results
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
com.xiang.spring.bean.Color
com.xiang.spring.bean.Red

2. Use ImportSelector to import bean s

(1) Define bean classes

public class Blue {
}

public class Yellow {
}

(2) Write selector

package com.xiang.spring.condition;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

/**
* Components to be imported for custom return logic
*/
public class MyImportSelector implements ImportSelector {
    /**
     * The return value is the full class name of the component imported into the container
     * AnnotationMetadata: All annotation information of the currently annotated @ Import class
     */
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        // Method does not return a null value
        return new String[]{"com.xiang.spring.bean.Blue", "com.xiang.spring.bean.Yellow"};
    }
}

(3) Configuration class addition

@Configuration
// When importing a component, the id is the full class name of the component by default
@Import({Color.class, Red.class, MyImportSelector.class})
public class MainConfig2 {

(4) Run it and see the results

@Test
public void test04(){
    // Get IOC container
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    String[] definitionNames = applicationContext.getBeanDefinitionNames();
    for (String name : definitionNames) {
        System.out.println(name);
    }
}

//results of enforcement
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
com.xiang.spring.bean.Color
com.xiang.spring.bean.Red
com.xiang.spring.bean.Blue
com.xiang.spring.bean.Yellow

3. Use ImportBeanDefinitionRegistrar to import beans

(1) Writing bean classes

public class RainBow {
}

(2) Registration class

package com.xiang.spring.condition;

import com.xiang.spring.bean.RainBow;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * AnnotationMetadata: Current class annotation information
     * BeanDefinitionRegistry: BeanDefinition Registration class
     *  All beans that need to be added to the container are registered manually by calling BeanDefinitionRegistry.registerBeanDefinition
     */
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean red = registry.containsBeanDefinition("com.xiang.spring.bean.Red");
        boolean blue = registry.containsBeanDefinition("com.xiang.spring.bean.Blue");
        if(red && blue) {
            // Specifies the bean definition information
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
            // Specify the bean name and register a bean
            registry.registerBeanDefinition("rainBow", rootBeanDefinition);
        }
    }
}

(3) Configuration class

@Configuration
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {

(4) Write test methods and see the results

@Test
public void test04(){
    // Get IOC container
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    String[] definitionNames = applicationContext.getBeanDefinitionNames();
    for (String name : definitionNames) {
        System.out.println(name);
    }
}

// Operation results
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
com.xiang.spring.bean.Color
com.xiang.spring.bean.Red
com.xiang.spring.bean.Blue
com.xiang.spring.bean.Yellow
rainBow

6, Create a bean using FactoryBean

1. Create a bean using FactoryBean

(1) Define FactoryBean

package com.xiang.spring.bean;

import org.springframework.beans.factory.FactoryBean;

/**
* Create a spring defined factory bean
*/
public class ColorFactoryBean implements FactoryBean<Color> {

    /**
     * Returns a Color object that will be added to the container
     * If it is not a singleton, the getObject method will be called every time the bean is obtained
     */
    public Color getObject() throws Exception {
        return new Color();
    }

    public Class<?> getObjectType() {
        return Color.class;
    }

    /**
     * Controls whether it is singleton
     * true: Single example, save a copy in the container
     * false: It is not a singleton, and a new instance will be created every time it is obtained
     */
    public boolean isSingleton() {
        return false;
    }
}

(2) Add FactoryBean to configuration class

@Bean
public ColorFactoryBean colorFactoryBean() {
    return new ColorFactoryBean();
}

(3) Test class view output results

@Test
public void test04(){
    // Get IOC container
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    String[] definitionNames = applicationContext.getBeanDefinitionNames();
    for (String name : definitionNames) {
        System.out.println(name);
    }
    // By default, the object created by the factory bean calling getObject is obtained
    Object colorFactoryBean = applicationContext.getBean("colorFactoryBean");
    System.out.println("colorFactoryBean Type of:" + colorFactoryBean.getClass());
    // To get the factory bean itself, we need to prefix the id with a & symbol: & colorfactorybean
    Object colorFactoryBean2 = applicationContext.getBean("&colorFactoryBean");
    System.out.println("colorFactoryBean2 Type of:" + colorFactoryBean2.getClass());
}

// Output results
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig2
colorFactoryBean
colorFactoryBean Type of: class com.xiang.spring.bean.Color
colorFactoryBean2 Type of: class com.xiang.spring.bean.ColorFactoryBean

7, bean component registration summary

Register components in container

(1) Package scanning + Component annotation (@ Controller/@Service/@Repository/@Component)

(2) , @ Bean [import components in third-party packages]

(3) , @ Import [quickly Import a component into the container]

      ① @ import (component to be imported into the container); The 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 register beans into the container

(4) . use the FactoryBean provided by Spring

      ① By default, the object created by the factory bean calling getObject is obtained

      ② To get the factory bean itself, we need to prefix the id with a & symbol: & colorfactorybean

Tags: Java Spring Spring Boot

Posted on Thu, 02 Dec 2021 18:15:45 -0500 by kristofferlc