1. Preface
Have worked in many companies, seen many projects, found@Autowired
and@Resource
The use is the same mess.
Used in a project@Autowired
Yes, useful@Resource
of,
Some classes are even used in a while@Autowired
, use it in a while@Resource
, although it does not affect the implementation of business functions, it looks really messy.
This blog mainly explains the differences between these two annotations.
2. Different sources
@Autowired
It is annotation of the Spring framework.
@Resource
is annotation for Java (from JSR-250) and is supported compatible with the Spring framework.
Note: JSR is the abbreviation of Java Specification Requests, which means Java specification proposal.
3. Different dependency search order
@Autowired
First look up by type, if there are multiple beans, then look up by name.
@Resource
First look up by name, and if it cannot be found, then look up by type.
3.1 Verify @Autowired first search by type, then search by name
First, create a new interface:
public interface NotificationService {
void send();
}
Then create the first implementation class:
import ;
@Service
public class EmailService implements NotificationService {
@Override
public void send() {
("Send email notification");
}
}
Then create a second implementation class:
import ;
@Service
public class SmsService implements NotificationService {
@Override
public void send() {
("Send SMS Notification");
}
}
Finally, create a new controller and use it@Autowired
To inject NotificationService:
import ;
import ;
@RestController("/dependency/injection/test")
public class NotificationController {
@Autowired
private NotificationService notificationService;
}
Start the project at this time and will be thrownabnormal,
The reason is that there are 2 Beans of NotificationService type, Spring is not sure which one to inject, which also proves that@Autowired
The default is to search by type first.
There are three solutions to solve this problem.
The first solution is to use@Primary
annotation:
import ;
import ;
@Service
@Primary
public class EmailService implements NotificationService {
@Override
public void send() {
("Send email notification");
}
}
Note: If there are multiple beans of the same type, Spring will be preferred@Primary
Annotation marker bean.
The second solution is to modify the field name:
@Autowired
private NotificationService emailService;
The third solution is to use@Qualifier
annotation:
@Autowired
@Qualifier("emailService")
private NotificationService notificationService;
Proof of the second and third solutions@Autowired
It is searched by name.
The difference between the two is that the second solution is to look up by field name (implicitly), and the third solution is to look up by specified name (explicitly).
3.2 Verify @Resource first search by name, then search by type
First, create a new interface:
public interface NotificationService {
void send();
}
Then create the first class (Note: Not an implementation class):
import ;
@Service
public class EmailService {
public void send() {
("Send email notification");
}
}
Then create a second class (Note: It is the implementation class):
import ;
@Service
public class SmsService implements NotificationService {
@Override
public void send() {
("Send SMS Notification");
}
}
Finally, create a new controller and use it@Resource
To inject NotificationService:
import ;
import ;
@RestController("/dependency/injection/test")
public class NotificationController {
@Resource
private NotificationService emailService;
}
Start the project at this time and will be thrownabnormal,
The reason is that the EmailService Bean found by field name is not the NotificationService type, which also proves that@Resource
The default is to search by name first.
There are two solutions to solve this problem,
The first solution is to explicitly specify the Bean name:
@Resource(name = "smsService")
private NotificationService emailService;
The second solution is to modify the field name:
@Resource
private NotificationService notificationService;
The second solution can be injected successfully, which also proves that@Resource
It is searched by type.
At this time, because NotificationService only has one implementation class SmsService, the direct injection is successful.
If you change the EmailService to the NotificationService implementation class:
import ;
@Service
public class EmailService implements NotificationService {
@Override
public void send() {
("Send email notification");
}
}
Then the project will be thrownabnormal.
4. Different parameters
@Autowired
There is only 1 required parameter.@Resource
There are 7 parameters such as name and type.
4.1 @Autowired parameters
@Autowired
There is only 1 parameter, as shown below:
public @interface Autowired {
boolean required() default true;
}
By default,@Autowired
The requirement dependency must exist, and can be passedrequired = false
Set to optional.
@Autowired(required = false)
private NotificationService notificationService;
4.2 @Resource parameters
@Resource
There are 7 parameters as follows:
public @interface Resource {
String name() default "";
String lookup() default "";
Class<?> type() default ;
enum AuthenticationType {
CONTAINER,
APPLICATION
}
AuthenticationType authenticationType() default ;
boolean shareable() default true;
String mappedName() default "";
String description() default "";
}
By default,@Resource
First look up the bean based on the field name. You can explicitly specify the name through the name parameter and explicitly specify the type through the type parameter.
@Resource(name = "emailService", type = )
private NotificationService notificationService;
5. The supported dependency injection methods are different
@Autowired
Supports field injection, Setter method injection and constructor injection.
@Resource
Supports field injection and Setter method injection, and does not support constructor injection.
5.1 @Autowired support for dependency injection
1) Field injection:
@RestController("/dependency/injection/test")
public class NotificationController {
@Autowired
private NotificationService notificationService;
}
This method is not recommended, but is used the most in actual projects.
2) Setter method injection:
@RestController("/dependency/injection/test")
public class NotificationController {
private NotificationService notificationService;
@Autowired
private void setNotificationService(NotificationService notificationService) {
= notificationService;
}
}
3) Constructor injection
@RestController("/dependency/injection/test")
public class NotificationController {
private final NotificationService notificationService;
public NotificationController(NotificationService notificationService) {
= notificationService;
}
}
This method is the preferred method officially recommended by Spring.
5.2 @Resource-supported dependency injection method
1) Field injection:
@RestController("/dependency/injection/test")
public class NotificationController {
@Resource
private NotificationService notificationService;
}
2) Setter method injection:
@RestController("/dependency/injection/test")
public class NotificationController {
private NotificationService notificationService;
@Resource
private void setNotificationService(NotificationService notificationService) {
= notificationService;
}
}
@Resource
Constructor injection is not supported, if used on the constructor@Resource
Annotation, IDEA will prompt:
'@Resource' not applicable to constructor。
6. Summary
@Autowired
and@Resource
They are all annotations used to implement dependency injection, but there are differences between the two, mainly the following 4 points:
-
Different sources
@Autowired
It is annotation of the Spring framework.@Resource
is annotation for Java (from JSR-250) and is supported compatible with the Spring framework. -
Different order of dependency search
@Autowired
First look up by type, if there are multiple beans, then look up by name.@Resource
First look up by name, and if it cannot be found, then look up by type. -
Different parameters
@Autowired
There is only 1 required parameter.@Resource
There are 7 parameters such as name and type. -
The supported dependency injection methods are different
@Autowired
Supports field injection, Setter method injection and constructor injection.@Resource
Supports field injection and Setter method injection, and does not support constructor injection.
The article continues to be updated, welcome to follow the WeChat public account "Shencheng Strange People" to read it as soon as possible!