(1)
@Autowired 表示某个属性是否需要进行依赖注入,可以写在属性和方法上。注解中的required属性默认为true,表示如果没有对象可以注入给属性则抛异常
@Autowired赋值过程:
1、Autowired加在某个属性上,Spring在进行Bean的生命周期过程中,在属性填充这一步,会基于实例化出来的对象,对该对象中加了Autowired的属性自动给属性赋值
Spring会根据属性的类型去Spring的容器中找出该类型所有的Bean对象,如果找出多个则在根据属性的名字从多个中确定一个,如果required为true并且根据属性信息找不到对象则抛出异常。2、Autowired加在某个方法上时,Spring在进行Bean生命周期的属性填充阶段,会根据方法的参数类型、参数名字从Spring容器中找到对象当做方法的入参,自动反射调用该方法。
3、Autowired加在构造方法上时,Spring会在推断构造方法阶段选择该构造方法进行实例化,在反射调用构造方法之前,会根据构造方法的参数类型,参数名从Spring容器中找到Bean对象,当做构造方法入参。
@Resource和@Autowired 类似,也是用来进行依赖注入的。@Resource是java所提供的注解 ,@Autowired 是Spring提供的,他们依赖注入的底层实现不同
@Resource赋值过程:
#Resource注解中有一个name属性,针对name属性是否有值,@Resource依赖注入的底层流程是不同的。
如果name属性有值,那么Spring会直接根据所指定的name值去Spring容器中找Bean对象,如果找到了则成功否者就会抛出异常
如果name属性没有值
1、先判断该属性名字在Spring容器中是否存在Bean对象
2、如果存在,则成功找到Bean对象进行注入
3、如果不存在,则根据属性类型去Spring容器中找Bean对象吗,找到一个则进行注入
@Value是什么
@Value和@Autowired、@Resource类似,也是用来对属性进行注入的,只不过@Value是用来从Properties文件中来获取值的,并且@Value可以解析SpEL(Spring表达式)
例:
1、@Value(“xiaoxiong”)
直接将字符串"xiaoxiong"赋值给属性,如果属性类型不是String,或无法进行类型转换,则报错
2、@Value("$ {xiaoxiong}")
将会把{}中的字符当做key从Properties文件中找出对应的Value赋值给属性如果没有找到则会把"$ {xiaoxiong}“当做普通字符赋值给属性
3、@Value(”#{xiaoxiong}")
会将#{}中的字符串当做Spring表达式进行解析,Spring会把xiaoxiong当做beanName,并从Spring容器中找到对应的Bean,如果找到则进行属性注入,没有找到则报错
(2)
联系
1.@Autowired和@Resource注解都是作为bean对象注入的时候使用的
2.两者都可以声明在字段和setter方法上
注意:如果声明在字段上,那么就不需要再写setter方法。但是本质上,该对象还是作为set方法的实参,通过执行set方法注入,只是省略了setter方法罢了
区别
1.@Autowired注解是Spring提供的,而@Resource注解是J2EE本身提供的
2.@Autowird注解默认通过byType方式注入,而@Resource注解默认通过byName方式注入
3.@Autowired注解注入的对象需要在IOC容器中存在,否则需要加上属性required=false,表示忽略当前要注入的bean,如果有直接注入,没有跳过,不会报错
简单来说,byName就是变量名去匹配bean的id属性,而byType则是变量类型去匹配bean的class属性
- <bean id="userService" class="com.test.UserServiceImpl">
- bean>
- @Autowired
- private UserService userService;
-
-
- @Resources
- private UserService userService;
此处byName就是拿变量名userService去匹配IOC容器的id userService,匹配成功;而byType就是拿变量类型UserService去匹配IOC容器的idcom.test.UserService.UserServiceImpl,因为UserServiceImpl是UserService实现,所以也匹配成功
(3)
@Autowired注解和@Resource注解的使用
@Autowird注解的使用
步骤:@Autowird默认的注入方式为byType,也就是根据类型匹配,当有多个实现时,则通过byName注入,也可以通过配合@Qualifier注解来显式指定name值,指明要使用哪个具体的实现类
举例:
首先有一个接口UserService和两个实现类UserServiceImpl1和UserServiceImpl2,并且这两个实现类已经加入到Spring的IOC容器中了
@Service
public class UserServiceImpl1 implements UserService@Service
public class UserServiceImpl2 implements UserService
通过@Autowired注入使用
- @Autowired
- private UserService userService;
根据上面的步骤,可以很容易判断出,直接这么使用是会报错的
原因:首先通过byType注入,判断UserService类型有两个实现,无法确定具体是哪一个,于是通过byName方式,这里的变量名userService也无法匹配IOC容器中id(此处指的userServiceImpl1和userServiceImpl2),于是报错。
注意:通过注解注入到IOC容器的id值默认是其类名首字母小写
解决方案
方式一:
- // 方式一:改变变量名
- @Autowired
- private UserService userServiceImpl1;
方式二:
- // 方式二:配合@Qualifier注解来显式指定name值
- @Autowired
- @Qualifier(value = "userServiceImpl1")
- private UserService userService;
步骤:@Resource默认通过byName注入,如果没有匹配则通过byType注入
举例:
- @Service
- public class UserServiceImpl1 implements UserService
-
- @Service
- public class UserServiceImpl2 implements UserService
-
-
-
- @Resource
- private UserService userService;
首先通过byName匹配,变量名userService无法匹配IOC容器中任何一个id(这里指的userServiceImpl1和userServiceImpl2),于是通过byType匹配,发现类型UserService的实现类有两个,仍然无法确定,于是报错。
同时@Resource还有两个重要的属性:name和type,用来显式指定byName和byType方式注入
- // 1. 默认方式:byName
- @Resource
- private UserService userService;
-
- // 2. 指定byName
- @Resource(name="userServiceImpl1 ")
- private UserService userService;
-
- // 3. 指定byType
- @Resource(type=UserService.class)
- private UserService userService;
-
- // 4. 指定byName和byType
- @Resource(name="userServiceImpl1 ",type=UserService.class)
- private UserService userService;