Spring 4.0 bis: @ Configuration usage

Keywords: Java Spring mvc

preface:
From Spring 3.0, @ Configuration is used to define the Configuration class, which can replace the xml Configuration file. The annotated class contains one or more methods annotated by @ bean. These methods will be scanned by the AnnotationConfigApplicationContext or AnnotationConfigWebApplicationContext class, and used to build the bean definition and initialize the Spring container.

Note: the Configuration class of @ Configuration annotation has the following requirements:
(1) @ Configuration cannot be final type;
(2) @ Configuration cannot be an anonymous class;
(3) Nested configuration must be a static class

1, Load spring with @ Configuration
1.@Configuration configures spring and starts the spring container
2. Start @ configuration container + @ Bean register Bean
3. Start @ configuration container + @ Component register Bean
4. Two methods of registering AppContext class with AnnotationConfigApplicationContext
5. Configure Web application (annotationconfigapplicationcontext is configured in web.xml)

2, Combine multiple configuration classes
1. Introduce the xml configuration file of spring in @ configuration
2. Introduce other annotation configurations in @ configuration
3.@configuration nesting (nested Configuration must be a static class)

1, @ configuration load Spring method

1.@Configuration configures spring and starts the spring container
@Configuration is marked on the class, which is equivalent to taking the class as a in the spring xml configuration file. Its function is to configure the spring container (application context)

package com.dxz.demo.configuration;

import org.springframework.context.annotation.Configuration;

@Configuration
public class TestConfiguration {
    public TestConfiguration() {
        System.out.println("TestConfiguration Container startup initialization...");
    }
}

amount to:

<?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" 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">

</beans>

Test by main method:

package com.dxz.demo.configuration;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestMain {
    public static void main(String[] args) {

        // @spring container loading method of Configuration annotation, replacing ClassPathXmlApplicationContext with AnnotationConfigApplicationContext
        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);

        // If the spring-context.xml file is loaded:
        // ApplicationContext context = new
        // ClassPathXmlApplicationContext("spring-context.xml");
    }
}

From the result of running the main method, we can see that the spring container has been started:

2. Start the @ configuration container + @ Bean, register the Bean, and manage the life cycle of the Bean under @ Bean
@The bean annotation on the method (the method that returns an instance) is equivalent to that in spring's xml configuration file. It is used to register bean objects

bean class:

package com.dxz.demo.configuration;

public class TestBean {

    private String username;
    private String url;
    private String password;

    public void sayHello() {
        System.out.println("TestBean sayHello...");
    }

    public String toString() {
        return "username:" + this.username + ",url:" + this.url + ",password:" + this.password;
    }

    public void start() {
        System.out.println("TestBean initialization...");
    }

    public void cleanUp() {
        System.out.println("TestBean Destroy...");
    }
}

Configuration class:

package com.dxz.demo.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
public class TestConfiguration {
    public TestConfiguration() {
        System.out.println("TestConfiguration Container startup initialization...");
    }

    // @bean annotation registers beans, and initialization and destruction methods can be specified at the same time
    // @Bean(name="testBean",initMethod="start",destroyMethod="cleanUp")
    @Bean
    @Scope("prototype")
    public TestBean testBean() {
        return new TestBean();
    }
}

Main method test class:

package com.dxz.demo.configuration;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestMain {
    public static void main(String[] args) {

        // @spring container loading method of Configuration annotation, replacing ClassPathXmlApplicationContext with AnnotationConfigApplicationContext
        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);

        // If the spring-context.xml file is loaded:
        // ApplicationContext context = new
        // ClassPathXmlApplicationContext("spring-context.xml");
        
         //Get bean
        TestBean tb = (TestBean) context.getBean("testBean");
        tb.sayHello();
    }
}

result:

Note:
(1) The @ bean annotation is on the method that returns the instance. If the bean name is not specified through @ bean, it is the same as the annotated method name by default;
(2) The default scope of @ bean annotation is the singleton scope of a single instance, which can be set as the prototype scope through @ Scope("prototype");
(3) Since @ bean is used to register bean objects, you can register beans with @ Component, @ Controller, @ Service, @ repository and other annotations. Of course, you need to configure the @ ComponentScan annotation for automatic scanning.

@Manage the life cycle of beans under bean

You can use Java based configuration to manage the lifecycle of beans@ Bean supports two attributes, initMethod and destroyMethod, which can be used to define life cycle methods. When the bean is instantiated or about to be destroyed, the container can call the lifecycle method. The lifecycle method is also called a callback method because it will be called by the container. Beans registered with the @ bean annotation also support the standard @ PostConstruct and @ PreDestroy annotations specified in JSR-250. If you are using XML methods to define beans, you should use bean elements to define lifecycle callback methods. The following code shows the method of defining callbacks using bean elements in XML configuration.

@Configuration
@ComponentScan(basePackages = "com.dxz.demo.configuration")
public class TestConfiguration {
    public TestConfiguration() {
        System.out.println("TestConfiguration Container startup initialization...");
    }

    //@bean annotation registers beans, and initialization and destruction methods can be specified at the same time
    @Bean(name="testBean",initMethod="start",destroyMethod="cleanUp")
    @Scope("prototype")
    public TestBean testBean() {
        return new TestBean();
    }
}

Startup class:

public class TestMain {
    public static void main(String[] args) {

        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);

        TestBean tb = (TestBean) context.getBean("testBean");
        tb.sayHello();
        System.out.println(tb);
        
        TestBean tb2 = (TestBean) context.getBean("testBean");
        tb2.sayHello();
        System.out.println(tb2);
    }
}

result:

analysis:
1 in the result: indicates that initMethod is effective
2 in the result: indicates that @ Scope("prototype") is effective

3. Start @ configuration container + @ Component register Bean
bean class:

package com.dxz.demo.configuration;

import org.springframework.stereotype.Component;

//Add annotation for registered bean
@Component
public class TestBean {

    private String username;
    private String url;
    private String password;

    public void sayHello() {
        System.out.println("TestBean sayHello...");
    }

    public String toString() {
        return "username:" + this.username + ",url:" + this.url + ",password:" + this.password;
    }

    public void start() {
        System.out.println("TestBean initialization...");
    }

    public void cleanUp() {
        System.out.println("TestBean Destroy...");
    }
}

Configuration class:

package com.dxz.demo.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
//Add auto scan annotation, and basePackages is the TestBean package path
@ComponentScan(basePackages = "com.dxz.demo.configuration")
public class TestConfiguration {
    public TestConfiguration() {
        System.out.println("TestConfiguration Container startup initialization...");
    }

    /*// @Bean Annotations register bean s, and initialization and destruction methods can be specified at the same time
    // @Bean(name="testNean",initMethod="start",destroyMethod="cleanUp")
    @Bean
    @Scope("prototype")
    public TestBean testBean() {
        return new TestBean();
    }*/
}

The main method test gets the bean object:

package com.dxz.demo.configuration;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestMain {
    public static void main(String[] args) {

        // @spring container loading method of Configuration annotation, replacing ClassPathXmlApplicationContext with AnnotationConfigApplicationContext
        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);

        // If the spring-context.xml file is loaded:
        // ApplicationContext context = new
        // ClassPathXmlApplicationContext("spring-context.xml");
        
         //Get bean
        TestBean tb = (TestBean) context.getBean("testBean");
        tb.sayHello();
    }
}

The sayHello() method is called normally.

4. Two methods of registering AppContext class with AnnotationConfigApplicationContext
(1) The configuration class is registered by passing it to the AnnotationConfigApplicationContext constructor

public static void main(String[] args) {

        // @spring container loading method of Configuration annotation, replacing ClassPathXmlApplicationContext with AnnotationConfigApplicationContext
        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);

        //Get bean
        TestBean tb = (TestBean) context.getBean("testBean");
        tb.sayHello();
    }

(2) The register method of AnnotationConfigApplicationContext passes in the configuration class to register the configuration class

public static void main(String[] args) {
  ApplicationContext ctx = new AnnotationConfigApplicationContext();
  ctx.register(AppContext.class)
}

5. Configure Web application (annotationconfigapplicationcontext is configured in web.xml)
In the past, you usually used the XMLWebApplicationContext context to configure Spring Web applications, that is, specify the path of 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 the external XML context file to 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>

Now you will change the above code in Web. XML to use the AnnotationConfigApplicationContext class. Remember that 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 use Java based configuration, so when configuring a Web application, you need to specify the AnnotationConfigApplicationContext class in the web.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>

The above modified web.xml now defines the AnnotationConfigWebApplicationContext context class as part of the context parameters and servlet elements. The context configuration location now points to the AppContext configuration class. It's very simple. The next section demonstrates the implementation of the bean's lifecycle callback and scope.

6. @ configuration summary
@Configuration is equivalent to
@Bean is equivalent to
@ComponentScan is equivalent to < context: component scan base package = "com.dxz.demo" / >

2, Combine multiple configuration classes

1. Introduce the xml configuration file of spring in @ configuration

package com.dxz.demo.configuration2;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

@Configuration
@ImportResource("classpath:applicationContext-configuration.xml")
public class WebConfig {
}

bean class:

package com.dxz.demo.configuration2;

public class TestBean2 {
    private String username;
    private String url;
    private String password;

    public void sayHello() {
        System.out.println("TestBean2 sayHello...");
    }

    public String toString() {
        return "TestBean2 username:" + this.username + ",url:" + this.url + ",password:" + this.password;
    }

    public void start() {
        System.out.println("TestBean2 initialization...");
    }

    public void cleanUp() {
        System.out.println("TestBean2 Destroy...");
    }
}

Test class:

package com.dxz.demo.configuration2;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestMain2 {
    public static void main(String[] args) {

        // @spring container loading method of Configuration annotation, replacing ClassPathXmlApplicationContext with AnnotationConfigApplicationContext
        ApplicationContext context = new AnnotationConfigApplicationContext(WebConfig.class);

        // If the spring-context.xml file is loaded:
        // ApplicationContext context = new
        // ClassPathXmlApplicationContext("spring-context.xml");

        // Get bean
        TestBean2 tb = (TestBean2) context.getBean("testBean2");
        tb.sayHello();
    }
}

result:

2. Introduce other annotation configurations in @ configuration

package com.dxz.demo.configuration2;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;

import com.dxz.demo.configuration.TestConfiguration;

@Configuration
@ImportResource("classpath:applicationContext-configuration.xml")
@Import(TestConfiguration.class)
public class WebConfig {
}

Test class:

package com.dxz.demo.configuration2;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.dxz.demo.configuration.TestBean;

public class TestMain2 {
    public static void main(String[] args) {

        // @spring container loading method of Configuration annotation, replacing ClassPathXmlApplicationContext with AnnotationConfigApplicationContext
        ApplicationContext context = new AnnotationConfigApplicationContext(WebConfig.class);

        // If the spring-context.xml file is loaded:
        // ApplicationContext context = new
        // ClassPathXmlApplicationContext("spring-context.xml");

        // Get bean
        TestBean2 tb2 = (TestBean2) context.getBean("testBean2");
        tb2.sayHello();
        
        TestBean tb = (TestBean) context.getBean("testBean");
        tb.sayHello();
    }
}

result:

3.@configuration nesting (nested Configuration must be a static class)
Through the configuration class nested configuration class, the purpose of combining multiple configuration classes is achieved. But note that the inner class must be static.
Upper Code:

package com.dxz.demo.configuration3;

import org.springframework.stereotype.Component;

@Component
public class TestBean {

    private String username;
    private String url;
    private String password;

    public void sayHello() {
        System.out.println("TestBean sayHello...");
    }

    public String toString() {
        return "username:" + this.username + ",url:" + this.url + ",password:" + this.password;
    }

    public void start() {
        System.out.println("TestBean start");
    }

    public void cleanUp() {
        System.out.println("TestBean destory");
    }
}
package com.dxz.demo.configuration3;

public class DataSource {

    private String dbUser;
    private String dbPass;
    public String getDbUser() {
        return dbUser;
    }
    public void setDbUser(String dbUser) {
        this.dbUser = dbUser;
    }
    public String getDbPass() {
        return dbPass;
    }
    public void setDbPass(String dbPass) {
        this.dbPass = dbPass;
    }
    @Override
    public String toString() {
        return "DataSource [dbUser=" + dbUser + ", dbPass=" + dbPass + "]";
    }
}

Configuration class:

package com.dxz.demo.configuration3;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "com.dxz.demo.configuration3")
public class TestConfiguration {
    public TestConfiguration() {
        System.out.println("TestConfiguration Container startup initialization...");
    }
    
    @Configuration
    static class DatabaseConfig {
        @Bean
        DataSource dataSource() {
            return new DataSource();
        }
    }
}

Startup class:

package com.dxz.demo.configuration3;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestMain {
    public static void main(String[] args) {

        // @spring container loading method of Configuration annotation, replacing ClassPathXmlApplicationContexts with AnnotationConfigApplicationContext
        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);

         //bean
        TestBean tb = (TestBean) context.getBean("testBean");
        tb.sayHello();
        
        DataSource ds = (DataSource) context.getBean("dataSource");
        System.out.println(ds);
    }
}

result:

TestConfiguration Container startup initialization...
TestBean sayHello...
DataSource [dbUser=null, dbPass=null]

Posted by Petrushka on Sat, 25 Sep 2021 23:27:15 -0700