@SpringBootApplication@Configuration@Configuration Load the Spring method. 1. @Configuration Configure Spring and start the Spring container Start the container + @ Bean registration bean3, @ Configuration start the container + @ Component registered Bean4, use AnnotationConfigApplicationContext AppContext Five classes of two methods, configure the Web application (Web. In the XML configuration AnnotationConfigApplicationContext) combining multiple configuration class in @ introduce spring’s XML configuration Configuration files introduce additional annotation configurations in @Configuration @Configuration nesting (nested configuration Must be a static class) @ EnableAutoConfigurationAutoConfigurationImportSelector

@SpringBootApplication

When developing with the Springboot framework, we usually add the @SpringBootApplication annotation to the main function to enable automatic configuration and component scanning of the application.

@SpringBootApplication

public class Application {



    public static void main(String[] args) {

        SpringApplication.run(Application.class, args);

    }

}

Copy the code

The @SpringBootApplication annotation is equivalent to the default properties using @Configuration, @EnableAutoConfiguration, and @ComponentScan,

You can look at the source code for the @SpringBootApplication annotation here.

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

@SpringBootConfiguration

@EnableAutoConfiguration

@ComponentScan(

    excludeFilters = {@Filter(

    type = FilterType.CUSTOM,

    classes = {TypeExcludeFilter.class}

), @Filter(

    type = FilterType.CUSTOM,

    classes = {AutoConfigurationExcludeFilter.class}

)}

)

public @interface SpringBootApplication {



}

Copy the code

The @SpringBootApplication annotation does not include @Configuration, which is actually inside @SpringBootConfiguration:

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Configuration

public @interface SpringBootConfiguration {

}

Copy the code

@SpringBootConfiguration inherits from @Configuration and has the same functionality, marking the current class as a Configuration class and incorporating into the Spring container one or more instances of methods declared in the current class marked with the @Bean annotation, and instance names being method names.

Here are the three annotations mentioned above.

@Configuration

Starting with Spring3.0, @configuration is used to define Configuration classes that can replace XML Configuration files, annotated classes that contain one or more @bean annotated methods, These methods will be AnnotationConfigApplicationContext or AnnotationConfigWebApplicationContext scanned, and used to construct the bean definition, initialize the Spring container.

Note: The @Configuration annotation modifies the Configuration class with the following requirements:

  1. Cannot be final;
  2. Can’t be anonymous classes;
  3. A nested Configuration must be a static class.

@configuration loads Spring methods

1. @Configuration configudes Spring and starts the Spring container

The @Configuration annotation is used on the class as a spring XML Configuration file to configure the Spring container (application context).

@Configuration

public class TestConfiguration {



    public TestConfiguration(a){

        System.out.println("TestConfiguration container starts initialization...");

    }

}

Copy the code

Is equivalent to


       

<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" xmlns:jdbc="http://www.springframework.org/schema/jdbc"

       xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"

       xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task"

       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd

        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd

        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd

        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd

        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd

        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd

        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd"
 default-lazy-init="false">


    <bean id="testConfiguration" class="com.example.configuration.TestConfiguration"></bean>

</beans>

Copy the code

The main method is tested:

public class TestMain {



    public static void main(String[] args) {

        / / @ Configuration annotations of the spring container loading way, replace with AnnotationConfigApplicationContext ClassPathXmlApplicationContext

// ApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfiguration.class);



        // Unannotate TestConfiguration by loading the spring-context. XML file

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-context.xml");

    }

}

Copy the code

There are two implementations of the above method, which can be tested separately and the following results can be obtained:

21:18:29.599 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'testConfiguration'

TestConfiguration container starts initialization...

Copy the code
@configuration starts the container + @bean to register the Bean

The @bean annotation on methods (methods that return an instance) is equivalent to the Spring XML configuration file: register Bean objects.

The bean class:

public class TestBean {

    private String username;

    private String url;

    private String password;



    public void sayHello(a){

        System.out.println("TestBean sayHello...");

    }



    public String toString(a){

        return "username:"+this.username+",url:"+this.url+",password:"+this.password;

    }



    public void start(a){

        System.out.println("TestBean initialization...");

    }



    public void cleanUp(a){

        System.out.println("TestBean destroyed...");

    }

}

Copy the code

The configuration class:

@Configuration

public class TestConfiguration2 {

    public TestConfiguration2(a){

        System.out.println("TestConfiguration container starts initialization...");

    }



    @Bean

    @Scope("prototype")

    public TestBean testBean(a){

        return new TestBean();

    }

}

Copy the code

Main method test class:

public class TestMain2 {



    public static void main(String[] args) {

        / / @ Configuration annotations of the spring container loading way, replace with AnnotationConfigApplicationContext ClassPathXmlApplicationContext

        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfiguration2.class);



        / / get a Bean

        TestBean testBean = (TestBean) applicationContext.getBean("testBean");

        testBean.sayHello();

        System.out.println(testBean.hashCode());



        If there is no @scope (" prototype ") attached to the testBean method, the @bean annotation defaults to the singleton Scope, so it returns the same object

        TestBean testBean1 = (TestBean) applicationContext.getBean("testBean");

        System.out.println(testBean1.hashCode());

    }

}

Copy the code

When the Bean class is not annotated with @scope (“prototype”), the output is:

09:12:58.279 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'testConfiguration2'

TestConfiguration container starts initialization...

09:12:58.282 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'testBean'

TestBean sayHello...

2143437117

2143437117

Copy the code

Annotated with @scope (“prototype”) output:

09:13:42.796 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'testConfiguration2'

TestConfiguration container starts initialization...

TestBean sayHello...

1989335500

1978869058

Copy the code

Conclusion:

  1. @BeanAnnotation on a method that returns an instance, if it fails@BeanSpecifying the bean name defaults to the method name of the annotation;
  2. @BeanThe default scope for annotations is the singleton scope, which can be passed@Scope("prototype")Set to stereotype scope;
  3. since@BeanIs used to register bean objects@Component,@Controller,@Service,@RipositorySuch annotations to register beans, of course, need to be configured@ComponentScanAnnotations are scanned automatically.
@Configuration starts the container +@Component to register the Bean

The bean class:

package com.example.domain;



import org.springframework.stereotype.Component;



@Component

public class BeanWithComponent {



    public void sayHello(a){



        System.out.println("BeanWithComponent sayHello...");

    }



    public void start(a){

        System.out.println("BeanWithComponent initializes...");

    }



    public void cleanUp(a){

        System.out.println("BeanWithComponent destroys...");

    }

}

Copy the code

The configuration class:

@Configuration

@ComponentScan(basePackages = "com.example.domain")

public class ComfigureWithScan {



    public ComfigureWithScan(a){

        System.out.println("Spring container startup initialization...");

    }

}

Copy the code

Main method test class:

public class TestComponnet {



    public static void main(String[] args) {

        ApplicationContext context = new AnnotationConfigApplicationContext(ComfigureWithScan.class);



        BeanWithComponent bean = (BeanWithComponent) context.getBean("beanWithComponent");

        bean.sayHello();

        System.out.println(bean);



        BeanWithComponent bean2 = (BeanWithComponent) context.getBean("beanWithComponent");

        System.out.println(bean2);

    }

}

Copy the code

The execution result is as follows:

10:03:56.791 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'comfigureWithScan'

Spring container starts initialization...

10:03:56.796 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanWithComponent'

BeanWithComponent sayHello...

com.example.domain.BeanWithComponent@d706f19

com.example.domain.BeanWithComponent@d706f19

Copy the code

As can be seen from the result, using @Component +@ComponentScan is equivalent to using @Bean without the @Scope annotation, i.e. the resulting Bean object is the same object.

4, use AnnotationConfigApplicationContext registered AppContext class two methods

A. Config classes are registered by passing them toAnnotationConfigApplicationContextThe constructor

public class TestComponnet {



    public static void main(String[] args) {

        ApplicationContext context = new AnnotationConfigApplicationContext(ComfigureWithScan.class);



    }

}

Copy the code

B,AnnotationConfigApplicationContextThe Register method passes in the configuration class to register it

public class TestComponnet {



    public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

        context.register(ComfigureWithScan.class);

        context.refresh();

        ApplicationContext ctx = context;



    }

}

Copy the code

This method is actually split of AnnotationConfigApplicationContext constructor is used, reference that part of the source code is as follows:

public AnnotationConfigApplicationContext(Class
        ... componentClasses) {

    this(a);

    this.register(componentClasses);

    this.refresh();

}

Copy the code

Note: The code for this section on the web looks like this:

public static void main(String[] args) {

  ApplicationContext ctx = new AnnotationConfigApplicationContext();

  ctx.register(AppContext.class)

}

Copy the code

I don’t know why they all passed the test, but I couldn’t code it locally, so I had to think about it differently. Here have a look at AnnotationConfigApplicationContext class structure hierarchy chart:

The analysis of this class, we will study it later.

5, configuration, Web application (Web. In the XML configuration AnnotationConfigApplicationContext)

In the past, you typically configured Spring Web applications with the XmlWebApplicationContext context, specifying the path to the external XML context file in the Web deployment descriptor file web.xml. XMLWebApplicationContext is the default context class used by Web applications. The following code describes the elements in web.xml that point to an external XML context file that will be loaded by the ContextLoaderListener listener class.

<web-app>

    <context-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>/WEB-INF/applicationContext.xml</param-value>

    </context-param>

    <listener>

        <listener-class>

            org.springframework.web.context.ContextLoaderListener

        </listener-class>

    </listener>

    <servlet>

    <servlet-name>sampleServlet</servlet-name>

    <servlet-class>

        org.springframework.web.servlet.DispatcherServlet

    </servlet-class>

    </servlet>

.

</web-app>

Copy the code

Now, you will web. XML in the above code changes for the use of AnnotationConfigApplicationContext class. Remember, XmlWebApplicationContext is the default context implementation used by Spring for Web applications, so you never have to explicitly specify this context class in your web.xml file. Now, you will be using Java based configuration, so in configuring a Web application, need on the Web. AnnotationConfigApplicationContext class specified in the XML file. The above code will be modified as follows:

<web-app>

    <context-param>

        <param-name>contextClass</param-name>

        <param-value>

            org.springframework.web.context.

            support.AnnotationConfigWebApplicationContext

        </param-value>

    </context-param>

    <context-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>

            demo.AppContext

        </param-value>

    </context-param>

    <listener>

        <listener-class>

            org.springframework.web.context.ContextLoaderListener

        </listener-class>

    </listener>

    <servlet>

    <servlet-name>sampleServlet</servlet-name>

    <servlet-class>

        org.springframework.web.servlet.DispatcherServlet

    </servlet-class>

    <init-param>

        <param-name>contextClass</param-name>

        <param-value>

            org.springframework.web.context.

            support.AnnotationConfigWebApplicationContext

        </param-value>

    </init-param>

    </servlet>



.

</web-app>

Copy the code

The above revised web. The XML defines AnnotationConfigWebApplicationContext context class now, as a part of the context parameter and servlet elements. The context configuration location now points to the AppContext configuration class.

Combine multiple configuration classes

Import Spring’s XML configuration file in @Configuration

The configuration class:

@Configuration

@ImportResource("classpath:applicationContext-configuration.xml")

public class TestConfiguration2 {

    public TestConfiguration2(a){

        System.out.println("TestConfiguration2 Container starts initialization...");

    }



// @Bean

// @Scope("prototype")

// public TestBean testBean(){

// return new TestBean();

/ /}

}

Copy the code

The bean class:

public class TestBean {



    public void sayHello(){



        System.out.println("TestBean sayHello...");

    }



    public void start(){

        System.out.println("TestBean initialization...");

    }



    public void cleanUp(){

        System.out.println("TestBean destroyed...");

    }

}

Copy the code

ApplicationContext – configuration. XML:


       

<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" xmlns:jdbc="http://www.springframework.org/schema/jdbc"

       xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"

       xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task"

       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd

        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd

        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd

        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd

        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd

        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd

        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd"
 default-lazy-init="false">


    <bean id = "testBean" class="com.example.domain.TestBean"></bean>

</beans>

Copy the code

The test class:

public class TestMain2 {



    public static void main(String[] args) {

        / / @ Configuration annotations of the spring container loading way, replace with AnnotationConfigApplicationContext ClassPathXmlApplicationContext

        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfiguration2.class);



        / / get a Bean

        TestBean testBean = (TestBean) applicationContext.getBean("testBean");

        testBean.sayHello();

        System.out.println(testBean);



        TestBean testBean1 = (TestBean) applicationContext.getBean("testBean");

        System.out.println(testBean1);

    }

}

Copy the code

The execution result is as follows:

16:35:28.837 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'testConfiguration2'

TestConfiguration2 Container starts initialization...

16:35:28.852 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'testBean'

TestBean sayHello...

com.example.domain.TestBean@78aab498

com.example.domain.TestBean@78aab498

Copy the code

While this combination can achieve the same effect, it seems simpler to use @Bean annotations directly in the configuration class.

Introduce additional annotation configurations in @Configuration

Modify the configuration class:

@Configuration

@ImportResource("classpath:applicationContext-configuration.xml")

@Import(TestConfiguration.class)

public class TestConfiguration2 {



}

Copy the code

The execution result is as follows:

16:40:40.239 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'com.example.configuration.TestConfiguration'

TestConfiguration container starts initialization...

16:40:40.239 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'testBean'

TestBean sayHello...

com.example.domain.TestBean@12e61fe6

com.example.domain.TestBean@12e61fe6

Copy the code
@Configuration nesting (a nested Configuration must be a static class)

By nested configuration classes, multiple configuration classes can be combined. But note that the inner class must be static.

The bean class:

package com.example.domain;

@Component

public class BeanWithComponent {



    public void sayHello(a){



        System.out.println("BeanWithComponent sayHello...");

    }



    public void start(a){

        System.out.println("BeanWithComponent initializes...");

    }



    public void cleanUp(a){

        System.out.println("BeanWithComponent destroys...");

    }

}

Copy the code
package com.example.domain;

public class DataSource {



    @Override

    public String toString(a) {

        return "I am DataSource";

    }

}

Copy the code

The configuration class:

@Configuration

@ComponentScan(basePackages = "com.example.domain")

public class ComfigureWithScan2 {



    public ComfigureWithScan2(a){

        System.out.println("The Spring container starts initialization... ComfigureWithScan2");

    }



    @Configuration

    static class DataConfigure{

        @Bean

        DataSource dataSource(a){

            return new DataSource();

        }

    }

}

Copy the code

The test class:

public class TestComponnet2 {



    public static void main(String[] args) {

        ApplicationContext context = new AnnotationConfigApplicationContext(ComfigureWithScan2.class);



        BeanWithComponent bean = (BeanWithComponent) context.getBean("beanWithComponent");

        bean.sayHello();



        DataSource dataSource = (DataSource) context.getBean("dataSource");

        System.out.println(dataSource);

    }

}

Copy the code

The execution result is as follows:

16:55:10.429 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'comfigureWithScan2'

Spring container starts initialization... ComfigureWithScan2

16:55:10.429 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanWithComponent'

16:55:10.429 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'com.example.configuration.ComfigureWithScan2$DataConfigure'

16:55:10.429 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'dataSource'

BeanWithComponent sayHello...

I am DataSource

Copy the code

Refer to the link: https://www.cnblogs.com/duanxz/p/7493276.html

@EnableAutoConfiguration

With the help of @import, @enableAutoConfiguration loads all bean definitions that qualify for automatic configuration into the Ioc container.

@enableAutoConfiguration is also a composite Annotation, with the following source code:

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

@AutoConfigurationPackage

@Import({AutoConfigurationImportSelector.class})

public @interface EnableAutoConfiguration {

    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";



Class<? >[] exclude()default {};



    String[] excludeName() default {};

}

Copy the code

One of the most critical is @ Import ({AutoConfigurationImportSelector. Class}), with the aid of AutoConfigurationImportSelector this class, @enableAutoConfiguration helps SpringBoot applications load all eligible @Configuration into the Ioc container created and used by the current SpringBoot application.

AutoConfigurationImportSelector

Before SpringBoot1.5, use EnableAutoConfigurationImportSelector, it inherits from AutoConfigurationImportSelector, after 1.5, EnableAutoConfigurationImportSelector already no longer been advised to use, but it is recommended to use AutoConfigurationImportSelector.

When it is executed

Springboot uses ConfigurationClassParser to parse the @Configuration modified Configuration class and then handle other annotations inside the class, such as the @import annotation, @ComponentScan annotations, @Bean annotations, etc.

If we find @import (ImportSelector) in the annotation, we create a corresponding ImportSelector object and call its selectImports method, And AutoConfigurationImportSelector is a ImportSelector implementation class. For more analysis of ConfigurationClassParser, see the Article :Spring Class Registration Notes

So ConfigurationClassParser will instantiate a selectImports AutoConfigurationImportSelector and call it () method.

public String[] selectImports(AnnotationMetadata annotationMetadata) {

    if (!this.isEnabled(annotationMetadata)) {

        return NO_IMPORTS;

    } else {

        AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);

        AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);

        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());

    }

}



protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {

    if (!this.isEnabled(annotationMetadata)) {

        return EMPTY_ENTRY;

    } else {

        AnnotationAttributes attributes = this.getAttributes(annotationMetadata);

        List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);

        configurations = this.removeDuplicates(configurations);

        Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);

        this.checkExcludedClasses(configurations, exclusions);

        configurations.removeAll(exclusions);

        configurations = this.filter(configurations, autoConfigurationMetadata);

        this.fireAutoConfigurationImportEvents(configurations, exclusions);

        return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);

    }

}

Copy the code

In selectImports method call getAutoConfigurationEntry () this method, in view you can see the method to obtain the configuration class code, concrete is getCandidateConfigurations () method, Click here to see the implementation:

Key class for automatic configuration :SpringFactoriesLoader

The main function of the SpringFactoriesLoader is to load the configuration from the specified configuration file, META/spring.factories, which is a typical Java properties file, The configuration format is key-value, except that both Key and Value are full class names of Java types.

LoadFactoryNames () reads the meta-INF/spring.Factories file under ClassPath.

In the case of @enableAutoConfiguration, it is more of a configuration lookup feature, According to the full name of the class of the @ EnableAutoConfiguration org. Springframework. Boot. Autoconfigure. EnableAutoConfiguration Get the corresponding set of @Configuration classes as the lookup key.

Due to the length of this article, the @Component annotation will be covered in the next chapter.