Instructions for using @ autowired @ Qualifier @ Primary annotations in spring

  • 2021-12-12 08:46:04
  • OfStack

Directory @ autowired, @ Qualifier, @ Primary annotation usage 1: When the current attribute is not required 2: Differences between multiple builds of the same type in the container @ Autowired @ Resource @ Qualifier @ Primary

Use of @ autowired, @ Qualifier, @ Primary annotations

Friends who have studied spring should all know the @ Autowired annotation, which injects the attributes in the IOC container into the current attributes.

1: When the current property is not required

The @ Autowired annotation has and only has this 1 attribute


@Autowired(required = false)

2: There are multiple builds of the same type in the container

1: Select the injected build by specifying that the name of the attribute is the same as that of the build id in the container

2: Inject the built id with @ Qualifier annotation selection


@Qualifier("bookDao2")
@Autowired(required = false)
private BookDao bookDao;

3: Specify which build to use when injecting a build with the @ Primary annotation, and the build with the @ Primary annotation will be preferred when injecting.

When using the @ Qualifier annotation and the @ Primary annotation at the same time, of course, the build specified by the @ Qualifier annotation is preferred


@Primary
@Bean(name = "bookDao2")
    public BookDao bookDao(){
        BookDao bookDao = new BookDao();
        bookDao.setLable(2);
        return bookDao;
    }

The difference between @ Autowired @ Resource @ Qualifier @ Primary

The difference between @ Autowired @ Resource @ Qualifier

Practical understanding: @ Autowired @ Resource 2 choose one, and use whichever you like.

Simple understanding:

@Autowired Depending on type injection, @Resource Inject by name by default, followed by search by type @Autowired @Qualifie(“userService”) The two can be combined to inject according to name and type

Complex understanding:

For example, you have such an Bean


@Service( " UserService " )
public Class UserServiceImpl implements UserService {} ;
 Now you want to UserController  Use this inside UserServiceImpl 
public Class UserController  { 
@AutoWire //When using this injection, the above UserServiceImpl only needs to write @ Service, which will automatically find the type UserService and its subtypes. UserServiceImpl implements UserService, so it can be found. However, this has a disadvantage, that is, when there are more than two UserService implementation classes, which one will be found at this time, which will cause conflicts, so make sure that UserService has only one implementation class when injecting with @ AutoWire. @Resource By default, it is matched by name. If Bean with the same name is not found, it will be matched by type. Some people may think, well, it is omnipotent to use this, regardless of name or type, but there are still shortcomings here. First of all, according to the matching effect of this annotation, It matches twice, that is to say, if you write an annotation on the class UserService like this, @ Service, how will it find it? First, find the same name, and if it can't find it, then find the same type, but @ Service here doesn't write a name, so it searches twice at this time, obviously, the speed drops a lot. Perhaps you will also ask, @ Service here has no name at all, so it must be a direct type search. In fact, this is not the case. If there is @ Service on UserServiceImpl, the default name is this userServiceImpl. Note that the upper case in front of the class name is changed to lowercase, which is the default name of Bean. @ Resource is written as @ Resource ("userService") according to the name search. If you write this name as userService, then UserServiceImpl must also have this name, otherwise you will still report an error. @Autowired @Qualifie(“userService”) Search directly by name, that is to say, the annotation of @ Service on UserServiceImpl must be named, and an error will be reported if it is not written, and the name must be @ Autowired @ Qualifie ("userService"). If @ Service has a name written on it and @ Autowired @ Qualifie (), one will report an error.

private UserService userService;
 } 

Having said so much, you may be dizzy, so how to use these three? The actual work should be used according to the actual situation. Usually, AutoWire and @ Resource are used more than one. The name of bean need not be written, but @ Service ("userService") can be written on UserServiceImpl. What is the actual working situation here? To put it bluntly, it is the consideration of the whole project design. If your architect considers it carefully and strictly, and requires the access speed after the project goes online to be better, it usually considers the speed. At this time, @ AutoWire is not as easy to use as @ Resource, because @ Resource can be searched by name, which is written as @ Resource ("userService"). This @ Autowired @ Qualifie ("userService") can also use a name. Why not use it? The reason is very simple. This one is a bit long, so I don't like it, which increases the workload. Because searching by name is the fastest, just like looking up database 1, searching by Id is the fastest. Because the name here is the same as ID in the database. At this time, you are required to write more names, and the workload will naturally increase. If you don't need annotations, when you use xml file, you need to write an Id when injecting Bean, and id when you use xml file is equivalent to the name here.

It's useless to say so much. What you can do is to be simple and direct, and use whatever is most convenient.

You can use @ Resource directly. If you like to use @ AutoWire, you don't need to write your name.

Usually, an Bean annotation is written incorrectly, and the following errors will be reported, which are the most common.

No bean named 'user' is defined, which means that Bean named user has not been found. Generally speaking, it is the type named user and its subtypes. The reason for this error is that the type name at the time of injection is user, but it cannot be found at the time of search, which means that there is no command for user. The solution is to find this type and command user.

The following error is also common,

No qualifying bean of type [com.service.UserService] found for dependency:

The reason for this error is that @ Service is not added to the type, not only @ Service, but also other layers. Here, I take Service as an example. If it is DAO layer, @ Repository and Controller layer are not added, then @ Controller is not added.

Also, if you still want to be simpler, you can use this annotation for DAO, Controller and Service, @ Component. This annotation is common to all Bean. At this time, you may say, why are there few people who use it usually? It is because of the layered design principle of MVC, using @ Repository, @ Service and @ Controller, which can distinguish DAO, Service and Controller in MVC principle. Easy to identify.

@Qualifier VS @Primary

There is another annotation named @ Primary, which we can also use to decide which bean to inject when ambiguity of dependency injection occurs. This annotation defines preferences when there are multiple bean of the same type. Unless otherwise stated, the bean associated with the @ Primary annotation is used.

Let's look at an example:


@Bean
public Employee tomEmployee() {
    return new Employee("Tom");
}
@Bean
@Primary
public Employee johnEmployee() {
    return new Employee("john");
}

In this example, both methods return the same Employee type. The bean that Spring will inject is the bean returned by the method johnEmployee. This is because it contains @ Primary annotations. This annotation is useful when we want to specify that a specific type of bean should be injected by default.

If we need another bean at some injection point, we need to specify it. We can do this with @ Qualifier annotation. For example, we can specify the bean we want to return using the tomEmployee method by using the @ Qualifier annotation.

It is worth noting that the @ Qualifier annotation takes precedence if both the @ Qualifier and @ Primary annotations exist. Basically, @ Primary defines default values, while @ Qualifier is very specific.

Of course, @ Component can also use the @ Primary annotation, this time using the above example:


@Component
 @Primary
 public class FooFormatter implements Formatter {
     public String format() {
         return "foo";
     }
 }
 
 @Component
 public class BarFormatter implements Formatter {
     public String format() {
         return "bar";
     }
 }

In this case, the @ Primary annotation specifies that FooFormatter is injected by default, eliminating injection ambiguity in the scenario.


Related articles: