现在作为Java开发,spring已经是必备的技能,而spring实现原理就是依赖注入,早期依赖注入需要通过配置xml文件,很繁琐,总是因为少写或写错bean,而前功尽弃,重新打包上线,要特别小心。后来有了注解注入,才轻松了很多。今天来说一下自动注入的前世今生,包括xml注入,自动注入,以及注解注入@Resource、@Autowired和@AllArgsConstructor等。今天来说下注入的那些事。
注入的方式
先说下注入的方式有哪些
常用的注入方式有,Setter方法注入、构造器注入、自动装配、注解注入等。
1.Setter方法注入
Setter方法注入就是通过在类中实现Set方法来实现属性或者对象的注入,如下所示
假如要给UserService类,要注入UserDao对象。先在标签中声明一个UserDao的Bean,然后把它注入到userService的bean里,然后再在UserSerice类里,使用它。写法如下
UserDao类
public class UserDao{
User getUserById(String userId);
}
UserService 类
public class UserSericeImpl{
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public User getUser(String userId){
User user = userDao.getUserById(userId);
...
}
}
xml配置
<bean id="userDao" class="com.murong.dao.UserDao"></bean>
<bean id="userService" class="com.murong.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
2.构造器注入
构造器注入就是通过类的构造器方法去注入
与Setter注入的主要区别就是在标签文件中,他把userService的bean里的Property替换成了constructor-arg,并且在类中的注入的Set方法改成了构造方法。
UserService 类
public class UserSericeImpl{
private UserDao userDao;
public UserSerice(UserDao userDao) {
this.userDao = userDao;
}
public User getUser(String userId){
User user = userDao.getUserById(userId);
...
}
}
xml配置
<bean id="userDao" class="com.murong.dao.UserDao"></bean>
<bean id="userService" class="com.murong.service.UserService">
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
3.自动装配
spring提供了自动装配的功能,简化了我们的配置,自动装配默认是不打开的,常用的方式有两种:
ByName: 通过参数名自动装配,如下所示,当userService的bean的autowire 被设置为ByName后,IOC容器会根据名字来自动装配,当发现userService类中有个userDao属性时,会看IOC容器中有没有Id为userDao的bean,有就装配进去。
<bean id="userDao" class="com.murong.UserDao"></bean>
<bean id="userService" class="com.murong.UserService" autowire="byName"/>
ByType:通过参数类型自动装配,当autowire被设置为byType后,IOC容器会看看里面有没有UserDao类型的,有就装配进去。
4.注解注入
随着时间的推移,使用xml的原始注入方式已经渐渐被注解注入替换,但底层原理还没有变,只是写法变了。
1.@Resource
先来说下@Resource ,Resurce注解是JDK1.6开始提供的一种注解方式,需要引入包(javax.annotation.Resource),它默认是通过名字(byName)来进行装配,当找不到与之匹配的名字时,才会按照类型(byType)进行匹配。如果都没有匹配上,或者找到了多个,就会报错。注入原理类似自动装配
实例如下
public class UserServiceImpl {
@Resource
private final UserDao userDao;
}
2.@Autowired
再来说下Autowired,Autowired 是Spring 提供的一种注解方式,需要引入包(org.springframework.beans.factory.annotation.Autowired),它默认是通过类型(byType)来进行注入.如果要使用byName注入,可以结合@Qualifier注解一起使用。
public class UserServiceImpl {
@Autowired
private final UserDao userDao;
}
public class UserServiceImpl {
@Autowired
@Qualifier("userDao")
private final UserDao userDao;
}
3.@ AllArgsConstructor
最后说下AllArgsConstructor, AllArgConstactor是第三方lombok提供的一种注解方式,他需要引入lombok包,它是使用在类上的注解,它会生成一个构造函数,这个构造函数包含所有已经声明的字段属性。原理就是按照构造器注入。有了AllArgsConstructor,你就不用在每一个字段属性上添加注解了。真的一个顶N个。
需要引入lombok
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
@AllArgsConstructor
public class UserServiceImpl {
private final UserDao userDao;
private final StudentDao studentDao;
private final CourseDao courseDao;
}
public class UserServiceImpl {
@Autowired
private final UserDao userDao;
@Autowired
private final StudentDao studentDao;
@Autowired
private final CourseDao courseDao;
}
注入可能出现的问题
注入可能出现循环依赖问题,例如AService依赖BService,并且BService又依赖AService这种情况,如果涉及到两个类的互相依赖时,运行时会报错。解决办法就是,都在AService处理,或者都在BService里处理。
总结
落(lao)胎了一周大概,终于生出来了,望各位客官喜欢