Writing in the front

[Spring topic] stopped more than a month, during the update of other topics, many friends have left a message said: Glacier, you [Spring topic] is not stopped more ah! In fact, it did not stop, but a lot of partners left messages saying that they were in urgent need of learning some knowledge and skills, so as to make it easier to jump ship. Ha ha, everyone knows! So I stopped for a while and wrote some articles on other topics. Now, continue to update the String topic.

Follow the glacier technology wechat official account, subscribe to more technical dry goods! If the article is helpful to you, please do not spare your likes, views, comments and forwarding, your support is the biggest motivation for me to continue to create!

The project source code has been submitted to GitHub: github.com/sunshinelyz…

Note that

The @autowired annotation

The @autowired annotation annotates class member variables, methods, and constructors for automatic assembly. The @autoWired annotation can be placed on classes, interfaces, and methods. Before using @AutoWired, we configured the attributes of a bean in the form of the following XML file.

<property name="Attribute name" value="Attribute value"/>
Copy the code

The source code for the @Autowired annotation is shown below.

package org.springframework.beans.factory.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
	boolean required(a) default true;
}
Copy the code

Autowired Notes:

(1) The default priority is to find the corresponding component in the container according to the type, and assign the value upon finding it;

(2) If multiple components of the same type are found, the attribute name is used as the id of the component to search in the IOC container.

@ the Qualifier annotations

@AutoWired is Autowired by type, and if you need to assemble by name, you need to use the @qualifier annotation.

The @qualifier annotation source is shown below.

package org.springframework.beans.factory.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
	String value(a) default "";
}
Copy the code

@ Primary annotations

Annotations are used in Spring, often using @autowired, which is automatically injected based on Type Type by default. However, in special cases where there may be several different implementation classes for the same interface, and only one implementation is adopted by default, you can use the @primary annotation to indicate which implementation class is preferred.

The source code for the @primary annotation is shown below.

package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Primary {

}
Copy the code

Automatically.

Before getting into the project, let’s talk about what Spring component autowiring is. The auto-assembly of Spring components is that Spring uses dependency injection, commonly known as DI, to assign dependencies to components in the IOC container.

The project of actual combat

Test the @autowired annotation

Here, we use the DAO, Service, and Controller created in the previous project as examples. The initial code for the DAO, Service, and Controller is shown below.

  • dao
package io.mykit.spring.plugins.register.dao;
import org.springframework.stereotype.Repository;
/ * * *@author binghe
 * @version 1.0.0
 * @descriptionThe test DAO */
@Repository
public class PersonDao {}Copy the code
  • service
package io.mykit.spring.plugins.register.service;
import io.mykit.spring.plugins.register.dao.PersonDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/ * * *@author binghe
 * @version 1.0.0
 * @descriptionTest Service */
@Service
public class PersonService {
    @Autowired
    private PersonDao personDao;
}
Copy the code
  • controller
package io.mykit.spring.plugins.register.controller;
import org.springframework.stereotype.Controller;
/ * * *@author binghe
 * @version 1.0.0
 * @descriptionTest controller */
@Controller
public class PersonController {
    @Autowired
    private PersonService personService;
}
Copy the code

As you can see, we use the @Autowired annotation to inject the Dao in the Service and the @Autowired annotation to inject the Service in the Controller. For testing purposes, we generate a toString() method in the PersonService class, as shown below.

package io.mykit.spring.plugins.register.service;
import io.mykit.spring.plugins.register.dao.PersonDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/ * * *@author binghe
 * @version 1.0.0
 * @descriptionTest Service */
@Service
public class PersonService {
    @Autowired
    private PersonDao personDao;

    @Override
    public String toString(a) {
        returnpersonDao.toString(); }}Copy the code

Here, we call personDao’s toString() method directly in the toString() method of the PersonService class and return it. In order to better demonstration effect, we in the project of IO. Mykit. Spring. Plugins. Register. The config package created under AutowiredConfig class, as shown below.

package io.mykit.spring.plugins.register.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/ * * *@author binghe
 * @version 1.0.0
 * @descriptionTests the Config configuration class */ for the autowiring component
@Configuration
@ComponentScan(value = { "io.mykit.spring.plugins.register.dao", "io.mykit.spring.plugins.register.service", "io.mykit.spring.plugins.register.controller"})
public class AutowiredConfig {}Copy the code

Next, to test the above application, we create the AutowiredTest class under the IO. Mykit.spring. test package in the project’s SRC /test/ Java directory, as shown below.

package io.mykit.spring.test;
import io.mykit.spring.plugins.register.config.AutowiredConfig;
import io.mykit.spring.plugins.register.service.PersonService;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/ * * *@author binghe
 * @version 1.0.0
 * @descriptionTest auto assembly */
public class AutowiredTest {
    @Test
    public void testAutowired01(a){
        // Create an IOC container
        AnnotationConfigApplicationContext context = newAnnotationConfigApplicationContext(AutowiredConfig.class); PersonService personService = context.getBean(PersonService.class); System.out.println(personService); context.close(); }}Copy the code

The test method is relatively simple, and I won’t go into too much detail here. Next, we run the testAutowired01() method of the AutowiredTest class and get the output information shown below.

io.mykit.spring.plugins.register.dao.PersonDao@10e92f8f
Copy the code

As you can see, the PersonDao information is output.

The question then arises: is the PersonDao we output in the PersonService class the same object as the PersonDao we retrieve directly from the Spring IOC container?

We can add a method to get the PersonDao object in the testAutowired01() method of the AutowiredTest class and output the PersonDao object as obtained, as shown below.

@Test
public void testAutowired01(a){
    // Create an IOC container
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AutowiredConfig.class);
    PersonService personService = context.getBean(PersonService.class);
    System.out.println(personService);
    PersonDao personDao = context.getBean(PersonDao.class);
    System.out.println(personDao);
    context.close();
}
Copy the code

We run the testAutowired01() method of the AutowiredTest class again, and the output information is shown below.

io.mykit.spring.plugins.register.dao.PersonDao@10e92f8f
io.mykit.spring.plugins.register.dao.PersonDao@10e92f8f
Copy the code

As you can see, the PersonDao object we output in the PersonService class is the same object as the PersonDao object we fetch directly from the IOC container.

What if there are multiple PersonDao objects in the Spring container?

First, to make it more intuitive to see which PersonDao object we are fitting with the @AutoWired annotation, we modify the PersonDao class by adding a remark field and assigning it a default value, as shown below.

package io.mykit.spring.plugins.register.dao;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Repository;
/ * * *@author binghe
 * @version 1.0.0
 * @descriptionThe test DAO */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Repository
public class PersonDao {
    private String remark = "1";
}
Copy the code

Next, we inject a PersonDao object into the AutowiredConfig class and display the name of the bean specifying the PersonDao object in the IOC container as personDao2 and assign the remark field of the PersonDao object to 2, as shown below.

  @Bean("personDao2")
  public PersonDao personDao(a){
      return new PersonDao("2");
  }
Copy the code

Currently, two PersonDao objects are injected into our IOC container. Which PersonDao object is attached to the @AutoWired annotation at this point?

Next, we run the testAutowired01() method of the AutowiredTest class with the output information shown below.

PersonDao{remark='1'}
Copy the code

By default, the @autoWired annotation finds the corresponding component in the container by type, and assigns the value if it finds it. If you find more than one component of the same type, use the attribute name as the component ID to look it up in the IOC container.

So how do we get @AutoWired to assemble personDao2? That’s a good question, but it’s actually quite simple. Let’s change the personDao in the PersonService class to personDao2, as shown below.

package io.mykit.spring.plugins.register.service;
import io.mykit.spring.plugins.register.dao.PersonDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/ * * *@author binghe
 * @version 1.0.0
 * @descriptionTest Service */
@Service
public class PersonService {
    @Autowired
    private PersonDao personDao2;
    @Override
    public String toString(a) {
        returnpersonDao2.toString(); }}Copy the code

At this point, we run the testAutowired01() method of the AutowiredTest class again, and the output information is shown below.

PersonDao{remark='2'}
Copy the code

As you can see, the command line now outputs information for personDao2.

Test the @qualifier annotation

By default, the @Autowired annotation finds the corresponding component in the container by type, and assigns the value if it finds it. If you find more than one component of the same type, use the attribute name as the component ID to look it up in the IOC container.

If there are multiple components of the same type in the IOC container, can we show which component to assemble with the @AutoWired annotation? Some friends will say: duh! If you ask me that, it must be ok! Yes, you can! Here, the @qualifier annotation comes in handy!

In the previous test case, the command line output PersonDao{remark=’2′} stated that the @AutoWired annotation assembly personDao2. How do we display the @AutoWired annotation assembly PersonDao?

Rather simply, we just need to add the @Qualifier annotation to the personDao2 field on the PersonService class to show that the @AutoWired annotation is assembled for the personDao, as shown below.

@Qualifier("personDao")
@Autowired
private PersonDao personDao2;
Copy the code

At this point, we run the testAutowired01() method of the AutowiredTest class again, and the output information is shown below.

PersonDao{remark='1'}
Copy the code

As you can see, although the field name is personDao2 at this point, we use the @Qualifier annotation to show that the @AutoWired annotation assemblies the personDao object, so the final result outputs the information for the personDao object.

Test for no components in the container

What happens if there is no corresponding component in the IOC container? At this point, we remove the @repository annotation on the PersonDao class and the @Bean annotation on the PersonDao () method in the AutowiredConfig class, as shown below.

package io.mykit.spring.plugins.register.dao;

/ * * *@author binghe
 * @version 1.0.0
 * @descriptionThe test DAO */
public class PersonDao {
    private String remark = "1";

    public String getRemark(a) {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    @Override
    public String toString(a) {
        return "PersonDao{" +
                "remark='" + remark + '\' ' +
                '} '; }}Copy the code
package io.mykit.spring.plugins.register.config;

import io.mykit.spring.plugins.register.dao.PersonDao;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/ * * *@author binghe
 * @version 1.0.0
 * @descriptionTests the Config configuration class */ for the autowiring component
@Configuration
@ComponentScan(value = { "io.mykit.spring.plugins.register.dao", "io.mykit.spring.plugins.register.service", "io.mykit.spring.plugins.register.controller"})
public class AutowiredConfig {
    public PersonDao personDao(a){
        PersonDao personDao = new PersonDao();
        personDao.setRemark("2");
        returnpersonDao; }}Copy the code

The personDao is no longer in the IOC container. We run the testAutowired01() method of the AutowiredTest class again, and the output information is as follows.

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'io.mykit.spring.plugins.register.dao.PersonDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Qualifier(value=personDao), @org.springframework.beans.factory.annotation.Autowired(required=true)}
Copy the code

We can see that Spring threw an exception, but the corresponding bean object was not found. Can we tell Spring not to report an error? That’s for sure! Spring’s exception messages give corresponding prompts.

{@org.springframework.beans.factory.annotation.Qualifier(value=personDao), @org.springframework.beans.factory.annotation.Autowired(required=true)}
Copy the code

The solution is to add an attribute required=false to @AutoWired of the PersonService class, as shown below.

@Qualifier("personDao")
@Autowired(required = false)
private PersonDao personDao2;
Copy the code

And we modify the toString() method of the PersonService, as shown below.

@Override
public String toString(a) {
    return "PersonService{" +
        "personDao2=" + personDao2 +
        '} ';
}
Copy the code

At this point, you also need to remove the code in the testAutowired01() method of the AutowiredTest class that gets the personDao directly from the IOC container, as shown below.

@Test
public void testAutowired01(a){
    // Create an IOC container
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AutowiredConfig.class);
    PersonService personService = context.getBean(PersonService.class);
    System.out.println(personService);
    context.close();
}
Copy the code

At this point, we run the testAutowired01() method of the AutowiredTest class again, and the output information is shown below.

PersonService{personDao2=null}
Copy the code

As you can see, when you add the attribute required=false to @AutoWired, Spring does not throw an exception even if there is no corresponding object in the IOC container. At this point, the assembled object is null.

Once the test is complete, we add the @Repository annotation to the PersonDao class again, and the @Bean annotation to the PersonDao () method in the AutowiredConfig class.

Test the @primary annotation

In Spring, there may be several different implementation classes for the same interface, and if only one implementation is adopted by default, you can use the @primary annotation to indicate which implementation class is preferred.

First, we add the @primary annotation to the personDao() method of the AutowiredConfig class. At this point, we need to remove the @qualifier annotation on the personDao field in the PersonService class. This is because the @qualifier annotation specifies which component is assembled to display. If the @qualifier annotation is used, the object of the @Qualifier annotation will be assembled regardless of whether the @primary annotation is used.

Once set up, we run the testAutowired01() method of the AutowiredTest class again, and the output information is shown below.

PersonService{personDao2=PersonDao{remark='2'}}
Copy the code

As you can see, remark has a value of 2, and the personDao injected in the AutowiredConfig class is assembled.

Next, we add the @Qualifier annotation again for the personDao field in the PersonService class, as shown below.

@Qualifier("personDao")
@Autowired(required = false)
private PersonDao personDao;
Copy the code

At this point, we run the testAutowired01() method of the AutowiredTest class again, and the output information is shown below.

PersonService{personDao=PersonDao{remark='1'}}
Copy the code

As you can see, Spring has assembled the personDao using the @Qualifier annotation.

Big welfare

Follow the wechat official account of “Glacier Technology” and reply the keyword “Design Mode” in the background to get the PDF document of “23 Design Modes in Simple Java”. Return keyword “Java8” to obtain the Java8 new features tutorial PDF. “Distributed traffic limiting solutions under 100 million levels of traffic” PDF document, the three PDFS are created by the glacial and collated super core tutorial, interview essential!!

Ok, that’s enough for today! Don’t forget to click a like, to see and forward, let more people see, learn together, progress together!!

Write in the last

If you think glacier wrote good, please search and pay attention to “glacier Technology” wechat public number, learn with glacier high concurrency, distributed, micro services, big data, Internet and cloud native technology, “glacier technology” wechat public number updated a large number of technical topics, each technical article is full of dry goods! Many readers have read the articles on the wechat public account of “Glacier Technology” and succeeded in job-hopping to big factories. There are also many readers to achieve a technological leap, become the company’s technical backbone! If you also want to like them to improve their ability to achieve a leap in technical ability, into the big factory, promotion and salary, then pay attention to the “Glacier Technology” wechat public account, update the super core technology every day dry goods, so that you no longer confused about how to improve technical ability!