依赖注入(Dependency Injection,简称DI)意思是由容器或者框架将被调用类注入给调用对象,以此来降低调用对象和被调用类之间的依赖关系。
依赖注入主要有2种不同的实现形式:
1. 构造函数注入(Constructor Injection)
2. 设值注入(Setter Injection)
1.构造函数注入
通过调用类的构造函数,并将被调用类当做参数传递给构造函数,以此实现注入。
example:
public class UserImpl implements UserDao {
private String name;
private String password;
public UserImpl(String name) {
this.name = name;
}
public UserImpl(String name, String password) {
this.name = name;
this.password = password;
}
@Override
public String toString() {
return "username="+name+" password="+password;
}
@Override
public void getUser() {
System.out.println(toString());
}
}
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
public void getUser() {
userDao.getUser();
}
}
xml配置文件的具体配置
<!--采用有参数的构造方法 userImpl是实现了userdao的实现类-->
<bean id="user" class="com.jsu.dao.Impl.UserImpl">
<constructor-arg index="0" value="zhangsan"/>
<constructor-arg index="1" value="123"/>
</bean>
<bean id="service1" class="com.jsu.service.serviceImpl.UserServiceImpl">
<property name="userDao" ref="user"/>
</bean>
上述的例子中service指定userImpl这个对象为UserDao,并将其注入给UserServiceImpl这个类。最终由UserDao这个对象完成getUser的功能。
2.设值注入
设值注入主要通过添加并使用被调用类的set的方法来完成注入。
example:
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void getUser() {
userDao.getUser();
}
}
xml配置信息与构造函数注入相同。但是上述的例子确实通过set方法将userdao对象注入给UserServiceImpl类。
注意二者的区别:
使用构造函数注入可以隐藏注入字段的信息,
使用设置注入需要明确指出注入字段的信息。
使用构造函数注入由参数下标决定注入的参数
使用设置注入则需要指明每个参数的名称。当参数较多时候使用设值注入则更加容易理解
两种注入方式的选择
Constructor-based or setter-based DI?
Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. Note that use of the @Required annotation on a setter method can be used to make the property a required dependency.
The Spring team generally advocates constructor injection as it enables one to implement application components as immutable objects and to ensure that required dependencies are not null. Furthermore constructor-injected components are always returned to client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.
Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection.
Use the DI style that makes the most sense for a particular class. Sometimes, when dealing with third-party classes for which you do not have the source, the choice is made for you. For example, if a third-party class does not expose any setter methods, then constructor injection may be the only available form of DI.
如果需要了解更具体的set注入方式 可参照官方文档: