V. automatic assembly of Spring

Posted by josaho on Mon, 28 Oct 2019 14:41:35 +0100

Spring auto assembly

Spring makes use of dependency injection (DI) to complete the assignment of the dependencies of various components in the IOC container.

[1]@Autowired

@Autowired annotation, which can annotate class member variables, methods and constructors to complete the work of automatic assembly.

Use @ Autowired to eliminate the set and get methods. Before using @ Autowired, we configured the properties of a bean as follows:

<property name="Attribute name" value="Attribute value"/>    

In this way, the configuration is cumbersome and there are many codes. The @ Autowired annotation was introduced in Spring 2.5.

Because the annotation is relatively simple, we will not use code examples here. Let's mainly talk about the principle of @ Autowired and the precautions for using it.

So what's the principle of using @ Autowired?

In fact, when the Spring container is started, the container automatically loads an Autowired annotation beanpostprocessor postprocessor. When the container scans @ Autowired, @ Resource or @ Inject, it will automatically find the required bean in the IOC container and assemble the properties to the object.

Here are two annotations @ Resource and @ Inject:

@Resource is implemented by JSR250 specification, and dependency injection is implemented by CommonAnnotationBeanPostProcessor class.

@Inject is implemented through the JSR330 specification, and the dependency injection is implemented by the AutowiredAnnotationBeanPostProcessor class.

The differences of the three notes are as follows:

@Autowired and @ Inject are basically the same, because both use the Autowired annotation bean post processor to handle dependency injection. The exception is @ Resource, which uses the CommonAnnotationBeanPostProcessor to handle dependency injection. Of course, both are beanpostprocessors.

By default, @ Resource is assembled according to the component name. It cannot support @ primary (annotated on the Bean of the configuration class, which is injected preferentially during automatic injection) and @ Autowired(required=false) functions.

@ Inject needs to import javax.inject package. Like @ Autowired, it does not support @ Autowired(required=false) function.

@Locations that Autowired can label:

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;
}

Annotation to constructor, parameter, method and property is to get the value of parameter component from container

  • Constructor: if the current class has only one parameter constructor, @ Autowired on this parameter constructor can be omitted.
  • Method: in the method of annotation @ Bean, parameters can be obtained from the container without annotation @ Autowired.

[2]Aware

The highlight of Spring dependency injection is that all your beans are unaware of the existence of Spring containers. That is, you can replace your container with another container, such as Goggle Guice, where the coupling between beans is very low.

But in the actual project, we inevitably need to use the Spring container's own functional resources. At this time, Bean must be aware of the existence of the Spring container to call the resources provided by Spring, which is the so-called Spring Aware. In fact, Spring Aware is designed by Spring to be used inside the framework. If you use Spring Aware, your Bean will be coupled with the Spring framework.

Such as BeanNameAware, BeanFactoryAware and ApplicationContextAware interfaces. Suppose our class inherits the BeanNameAware interface, and there is a method of setBeanName corresponding to this interface. spring will call the method of the generated object in the initialization phase of dependency injection, passing beanName as an input parameter. Generally, we define a property in the class that we will write to receive the beanName, and then we can use the beanName in development.

Common Aware interfaces:

Aware sub interface describe
BeanNameAware Get the name of the Bean in the container
BeanFactoryAware Get the current BeanFactory
ApplicationContextAware Get current container
MessageSourceAware Related to internationalization
ApplicationEventPublisherAware Mainly used to publish events
ResourceLoaderAware Get the resource loader to get the external resource file

Take the implementation of BeanNameAware as an example:

public class Person implements BeanNameAware {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Person() {
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
    
    @Override
    public void setBeanName(String s) {
        this.name = s;
    }
}

Inject Person into the configuration class

@Configuration
public class MyConfig {
    @Bean("Jack")
    public Person person(){
        return new Person();
    }
}

/**Get the Bean in the test class and print it
Person{name='Jack'}
*/

[3]@Profile

1. What is @ Profile in spring?

The Profile function in Spring has been released as early as Spring 3.1. It can be understood as the logical group name of the Bean defined in the Spring container. Only when these profiles are activated will the Bean corresponding to the Profile be registered in the Spring container. For a more specific example, when the Spring container is started, all the beans we defined before will be loaded to complete the creation of the Bean. After using the Profile, it will divide the definition of the Bean into several different groups. When the Spring container loads the configuration information, first check Find the active Profile, and then load only the Bean information defined in the active group, while the Bean information defined in the inactive Profile will not be loaded for Bean creation.

2. How to use @ profile

Next, we define two data sources, which are specified in the test and development phases with @ Profile annotation.

@Configuration
public class MyConfig {
    @Bean
    @Profile("test")
    public DataSource dataSourceTest() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc.driver");
        dataSource.setJdbcUrl("jdbc:mysql:///test");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        return dataSource;
    }
    @Bean
    @Profile("dev")
    public DataSource dataSourceDev() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc.driver");
        dataSource.setJdbcUrl("jdbc:mysql:///test");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        return dataSource;
    }
}

In the test class, we set the current activation environment to test:

public class ProfileTest {
    @Test
    public void test(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        environment.setActiveProfiles("test");
        applicationContext.register(MyConfig.class);
        applicationContext.refresh();
        String[] names = applicationContext.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
    }
}

/**test result
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myConfig
dataSourceTest
*/

When the current environment is a test environment, only dataSourceTest is injected into the container.

The @ Profile can be labeled not only on methods, but also on classes, that is, the entire class is loaded according to the environment.

Topics: Java Spring MySQL JDBC Attribute