Spring's javabean(POJ) is implemented by java configuration

Keywords: Spring Java Maven xml

The following reprints are from Spring's Java Configuration In order to better understand, I have modified some parts, which are basically unchanged.

Java configuration is recommended by Spring 4. X and can completely replace xml configuration.

1 @Configuration and @Bean

Spring's java beans are configured in java through @Configuration and @Bean annotations:

1. @Configuration acts on classes, which is equivalent to an xml configuration file.

2. @Bean acts on the method, which is equivalent to <bean> in xml configuration.

2 examples

This example demonstrates how to configure Spring through Java configuration, and implements Spring IOC function.

2.1 Create Engineering and Import Dependency (Maven)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>cn.qiaoliqiang</groupId>
    <artifactId>spring-boot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>
        <!-- Connection pool -->
        <dependency>
            <groupId>com.jolbox</groupId>
            <artifactId>bonecp-spring</artifactId>
            <version>0.8.0.RELEASE</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <!-- Resource File Copy Plug-in -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <!-- java Compiler plug-in -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <!-- To configure Tomcat Plug-in unit -->
                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <version>2.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

2.2 Write User Objects (as usual)

package cn.qlq;
public class User {
    private String username;
    private String password;
    private int age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

2.3 Write UserDAO to simulate interaction with the database (note that this DAO is not annotated)

If you use Mybatis, it should be xml. Don't worry about that much. The point is not to inject javaBean(POJO) through xml.

package cn.qlq;

import java.util.ArrayList;
import java.util.List;

/**
 * Simulate UserDao query database
 * 
 * @author liqiang
 *
 */
public class UserDao {
    /**
     * Simulated 10 users
     * 
     * @return
     */
    public List<User> queryUserList() {
        List<User> result = new ArrayList<User>();
        // Query of Analog Database
        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setUsername("username_" + i);
            user.setPassword("password_" + i);
            user.setAge(i + 1);
            result.add(user);
        }
        return result;
    }

}

2.4 Write UserService to implement User data operation business logic (declare service annotations and automatically inject dao objects)

No difference.

package cn.qlq;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

//Declarations are service layer objects
@Service
public class UserService {
    @Autowired // Automatic injection of dao layer objects in Spring containers (byType injection)
    private UserDao UserDao;

    public List<User> queryUserList() {
        // Call the method in userDAO to query
        return this.UserDao.queryUserList();
    }

}

2.5 Write Spring Config for instantiating Spring containers (emphasis)

Enter the @Configuration annotation and the @ComponentScan configuration scan package.

@ Beans are used to put objects into containers, and if you annotate @Repository in front of the UserDao class, you don't need the @Bean way.

package cn.qlq;

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

@Configuration // This annotation indicates that this class is a Spring configuration, equivalent to an xml file
@ComponentScan(basePackages = "cn.qlq") // Configure the scanning package and change the way you scan the package in xml to this
public class SpringConfig {
	//Think of this as a factory model.
    @Bean // This annotation indicates that it is a Bean object, which is equivalent to < Bean > in xml.
    public UserDao getUserDAO() {
        return new UserDao(); // Direct new object for demonstration
    }

}

Note: The method name is used as the name of the return object, so get is not usually used, that is, the name of the bean put in the spring container is getUserDAO.

2.6 Write test methods to start Spring containers

package cn.qlq;

import java.util.List;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * Test class
 * 
 * @author liqiang
 *
 */
public class Test {

    public static void main(String[] args) {
        // Instantiating Spring containers through Java configuration
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

        // Getting Bean Objects in Spring Containers
        UserService userService = context.getBean(UserService.class);

        // Calling methods in objects
        List<User> list = userService.queryUserList();
        for (User user : list) {
            System.out.println(user.getUsername() + ", " + user.getPassword() + ", " + user.getPassword());
        }

        // Destroy the container
        context.destroy();
    }

}

Result:

username_0, password_0, password_0
username_1, password_1, password_1
username_2, password_2, password_2
username_3, password_3, password_3
username_4, password_4, password_4
username_5, password_5, password_5
username_6, password_6, password_6
username_7, password_7, password_7
username_8, password_8, password_8
username_9, password_9, password_9

Summary:

As you can see from the examples above, using Java code is a perfect alternative to xml configuration files, and the structure is clearer.

Usage method:

Spring's support for Java configuration is implemented by @Configuration annotations and @Bean annotations. The @Bean annotated method instantiates, configures, and initializes a new object, which will be managed by Spring's IoC container. @ Bean declarations play a similar role to <bean/> elements. Classes annotated by @Configuration indicate that the main purpose of this class is to serve as resources defined by beans. Classes declared by @Configuration can set the dependencies of embedded beans by calling the @bean method within the same class.

The simplest @Configuration declaration class refers to the following code: (the name put in spring is the method name, so get is not usually added)

@Configuration    
public class AppConfig{    
    @Bean    
    public MyService myService() {    
        return new MyServiceImpl();    
    }    
}  

For the above @Beans configuration file, the same XML configuration file is as follows:

<beans>    
    <bean id="myService" class="com.somnus.services.MyServiceImpl"/>    
</beans> 

The above configuration is instantiated in the following way: using AnnotationConfigApplicationContext class to instantiate

public static void main(String[] args) {    
    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);    
    MyService myService = ctx.getBean(MyService.class);    
    myService.doStuff();    
} 

To use component build scans, just annotate with @Configuration:

@Configuration    
@ComponentScan(basePackages = "com.somnus")    
public class AppConfig  {    
    ...    
}  

In the example above, the com.acme package is scanned first, then the classes declared by @Component are found in the container and registered according to the Sring bean definition.

Supplement: On parameter injection of @Bean:

@Bean
public User user2(User user) { 
    System.out.println("user is -> "+ user);
    User user2 = new User();
    user2.setUsername("user2");
    return user2;
}

If there is only one bean of User type in the spring container, then no matter what the name of the parameter is, the bean user is taken as the parameter by type. If there are more than one, the parameter name must be one of the beans, otherwise the error will be reported.

For example, the following error will be reported:

@Bean
public User user1() {
    User user = new User();
    user.setUsername("user1");
    return user;
}

@Bean
public User user2(User user) { 
    System.out.println("user is -> "+ user);
    User user2 = new User();
    user2.setUsername("user2");
    return user2;
}

@Bean
public User user3(User user) { 
    System.out.println("user is -> "+ user);
    User user2 = new User();
    user2.setUsername("user2");
    return user2;
}

Description:

Parameter 0 of method user2 in cn.qlq.config.RedisCacheConfig required a single bean, but 2 were found:

  • user1: defined by method 'user1' in class path resource [cn/qlq/config/RedisCacheConfig.class]
  • user3: defined by method 'user3' in class path resource [cn/qlq/config/RedisCacheConfig.class]

Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

Successful modification to the following:

@Bean
public User user1() {
    User user = new User();
    user.setUsername("user1");
    return user;
}

@Bean
public User user2(User user1) { 
    System.out.println("user1 is -> "+ user1);
    User user2 = new User();
    user2.setUsername("user2");
    return user2;
}

@Bean
public User user3(User user2) { 
    System.out.println("user2 is -> "+ user2);
    User user23 = new User();
    user23.setUsername("user3");
    return user23;
}

Start viewing injection information: (multiple types are injected by name)

user1 is -> User [id=null, username=user1, password=null, userfullname=null, createtime=null, isdeleted=null, sex=null, address=null]
user2 is -> User [id=null, username=user2, password=null, userfullname=null, createtime=null, isdeleted=null, sex=null, address=null]

Posted by stevengunn on Tue, 30 Jul 2019 08:32:17 -0700