@Autowired
@Autowired为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired。
@Autowired采取的策略为按照类型注入。
public class UserService {
@Autowired
private UserDao userDao;
}
如上代码所示,这样装配回去spring容器中找到类型为UserDao的类,然后将其注入进来。这样会产生一个问题,当一个类型有多个bean值的时候,会造成无法选择具体注入哪一个的情况,这个时候我们需要配合着@Qualifier使用。
@Qualifier告诉spring具体去装配哪个对象。
public class UserService {
@Autowired
@Qualifier(name=“userDao1”)
private UserDao userDao;
}
这个时候我们就可以通过类型和名称定位到我们想注入的对象。
@Resource
@Resource注解由J2EE提供,需要导入包javax.annotation.Resource。
@Resource默认按照ByName自动注入。
public class UserService {
@Resource
private UserDao userDao;
@Resource(name=“studentDao”)
private StudentDao studentDao;
@Resource(type=“TeacherDao”)
private TeacherDao teacherDao;
@Resource(name=“manDao”,type=“ManDao”)
private ManDao manDao;
}
①如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
②如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
③如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
④如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。
总结:
Spring属于第三方的,J2EE是Java自己的东西。使用@Resource可以减少代码和Spring之间的耦合。
两者都可以写在字段和setter方法上。两者如果都写在字段上,那么就不需要再写setter方法。
当存在多个类型,却又没有指定的时候,会报如下的错误:
Noqualifying bean of type
想必你在项目中使用如下代码时经常会看到idea提示了一个警告:Field injection is not recommended
image.png
@Autowired
UserDao userDao;
这个警告的意思就是使用变量依赖注入的方式是不被推荐的。那么为什么编译器要提示这个警告呢?idea给出的解决策略是这样的
Always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencies
意思就是总是使用构造器的方式强制注入。要了解为什么编译器推荐使用构造器的方式需要先了解spring的三种依赖注入的方式。
spring中的三种依赖注入方式
变量(filed)注入
@Autowired
UserDao userDao;
造器注入
final
UserDao userDao;
@Autowired
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
set方法注入
private UserDao userDao;
@Autowired
public void setUserDao (UserDao userDao) {
this.userDao = userDao;
}
如你所见,变量(filed)注入的方式是如此的简洁,没关。但实际上他是有一些问题的,具体问题如下
字段注入的缺点
只需要使用 @Autowired 就很容易的进行依赖注入,为什么说这是个缺点呢,因为这种方便可能让你放弃对依赖的思考,结果就是你的类的依赖可能是十几个或者更多,这样违反了SPR.
对单元测试不友好,你没办法直接初始化这个类,必须依赖 DI 容器.
类的依赖被隐藏起来,并不能像构造函数那样在初始化时,就直观的知道这个类有哪些依赖.
你的类跟DI容器强耦合在一起.
不能有效的指明依赖。
相信很多人都遇见过一个bug,依赖注入的对象为null,在启动依赖容器时遇到这个问题都是配置的依赖注入少了一个注解什么的。这种方式就过于依赖注入容器了,当没有启动整个依赖容器时,这个类就不能运转,在反射时无法提供这个类需要的依赖。
依赖注入的核心思想之一就是被容器管理的类不应该依赖被容器管理的依赖,换成白话来说就是如果这个类使用了依赖注入的类,那么这个类摆脱了这几个依赖必须也能正常运行。然而使用变量注入的方式是不能保证这点的。
而如果是采用构造器注入或者set注入,就可以避免上诉问题。
使用set方式时,这是一种选择注入,可有可无,即使没有注入这个依赖,那么也不会影响整个类的运行。
使用构造器方式时已经显式注明必须强制注入。通过强制指明依赖注入来保证这个类的运行。
总结
变量方式注入应该尽量避免,使用set方式注入或者构造器注入,这两种方式的选择就要看这个类是强制依赖的话就用构造器方式,选择依赖的话就用set方法注入。