Spring IOC 自动装配(注入)
Spring IOC 自动装配(注入)
注解⽅式注⼊ Bean
对于 bean 的注⼊,除了使⽤ xml 配置以外,可以使⽤注解配置。注解的配置,可以简化配置⽂件,提⾼开发的速度,使程序看上去更简洁。
对于注解的解释,Spring对于注解有专⻔的解释器,对定义的 注解进⾏解析,实现对应bean对象的注⼊。通过反射技术实现。
准备环境
1、修改配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
2、开启自动化注入
<!--开启⾃动化装配(注⼊)-->
<context:annotation-config/>
<bean id="userDao" class="com.xxxx.dao.UserDao"></bean>
<bean id="userService" class="com.xxxx.service.UserService"></bean>
3、给注入的bean对象添加注解
@Resource注解
@Resource注解实现⾃动注⼊(反射)
- 默认根据属性字段名称查找对应的bean对象 (属性字段的名称与bean标签的id属性值相等)
- 如果属性字段名称未找到,则会通过类型(Class类型)查找
- 属性可以提供set方法,也可以不提供set方法
- 注解可以声明在属性级别 或 set方法级别
- 可以设置name属性,name属性值必须与bean标签的id属性值⼀致;如果设置了name属性值,就只会按照name属性值查找bean对象
- 当注入接口时,如果接口只有⼀个实现则正常实例化;如果接口存在多个实现,则需要使用name属性指定需要被实例化的bean对象
注意:JDK11无法在Spring中使用@Resource注解
JDK11将javax.annotation这个包移除了,所以可以通过maven或者其他方式导入。如果这个依赖无法使用,可以去MVN上自行查找。
<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
代码示例:
1、默认根据属性字段名称查找对应的bean对象 (属性字段的名称与bean标签的id属性值相等)
/**
* @Resource注解实现⾃动注⼊(反射)
* 默认根据属性字段名称查找对应的bean对象 (属性字段的名称与bean标签的id属性值相等)
*/
public class UserService {
@Resource
private UserDao userDao; // 属性字段的名称与bean标签的id属性值相等
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void test() {
// 调⽤UserDao的⽅法
userDao.test();
}
}
2、 如果属性字段名称未找到,则会通过类型(Class类型)查找
/**
* @Resource注解实现⾃动注⼊(反射)
* 如果属性字段名称未找到,则会通过类型(Class类型)查找
*/
public class UserService {
@Resource
private UserDao ud; // 当在配置⽂件中属性字段名(ud)未找到,则会查找对应的
class(UserDao类型)
public void setUd(UserDao ud) {
this.ud = ud;
}
public void test() {
// 调⽤UserDao的⽅法
ud.test();
}
}
3、 属性可以提供set⽅法,也可以不提供set⽅法
/**
* @Resource注解实现⾃动注⼊(反射)
* 属性可以提供set⽅法,也可以不提供set⽅法
*/
public class UserService {
@Resource
private UserDao userDao; // 不提供set⽅法
public void test() {
// 调⽤UserDao的⽅法
userDao.test();
}
}
4、注解可以声明在属性级别 或 set⽅法级别
/**
* @Resource注解实现⾃动注⼊(反射)
* 注解可以声明在属性级别 或 set⽅法级别
*/
public class UserService {
private UserDao userDao;
@Resource // 注解也可设置在set⽅法上
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void test() {
// 调⽤UserDao的⽅法
userDao.test();
}
}
5、 可以设置name属性,name属性值必须与bean标签的id属性值⼀致;如果设置了name属性值,就只会按照name属性值查找bean对象
/**
* @Resource注解实现⾃动注⼊(反射)
* 可以设置name属性,name属性值必须与bean的id属性值⼀致;
* 如果设置了name属性值,就只会按照name属性值查找bean对象
*/
public class UserService {
@Resource(name = "userDao") // name属性值与配置⽂件中bean标签的id属性值⼀致
private UserDao ud;
public void test() {
// 调⽤UserDao的⽅法
ud.test();
}
}
6、 当注⼊接⼝时,如果接⼝只有⼀个实现则正常实例化;如果接⼝存在多个实现,则需要使⽤name属性指定需要被实例化的bean对象
定义接⼝类 IUserDao.java
package com.xxxx.dao;
/**
* 定义接⼝类
*/
public interface IUserDao {
public void test();
}
定义接⼝实现类 UserDao01.java
package com.xxxx.dao;
/**
* 接⼝实现类
*/
public class UserDao01 implements IUserDao {
@Override
public void test(){
System.out.println("UserDao01...");
}
}
定义接⼝实现类 UserDao02.java
package com.xxxx.dao;
/**
* 接⼝实现类
*/
public class UserDao02 implements IUserDao {
@Override
public void test(){
System.out.println("UserDao02...");
}
}
XML配置⽂件
<!--开启⾃动化装配(注⼊)-->
<context:annotation-config/>
<bean id="userService" class="com.xxxx.service.UserService"></bean>
<bean id="userDao01" class="com.xxxx.dao.UserDao01"></bean>
<bean id="userDao02" class="com.xxxx.dao.UserDao01"></bean>
使⽤注解 UserService.java
/**
* @Resource注解实现⾃动注⼊(反射)
* 当注⼊接⼝时,如果接⼝只有⼀个实现则正常实例化;如果接⼝存在多个实现,则需要使⽤
name属性指定需要被实例化的bean对象
*/
public class UserService {
@Resource(name = "userDao01") // name属性值与其中⼀个实现类的bean标签的id属
性值⼀致
private IUserDao iUserDao; // 注⼊接⼝(接⼝存在多个实现)
public void test() {
iUserDao.test();
}
}
@Autowired注解
@Autowired注解实现自动化注入:
- 默认通过类型(Class类型)查找bean对象 与属性字段的名称无关
- 属性可以提供set方法,也可以不提供set方法
- 注解可以声明在属性级别 或 set方法级别
- 可以添加@Qualifier结合使用,通过value属性值查找bean对象(value属性值必须要设置,且值要与bean标签的id属性值对应)
1、默认通过类型(Class类型)查找bean对象 与属性字段的名称⽆关
/**
* @Autowired注解实现⾃动化注⼊
* 默认通过类型(Class类型)查找bean对象 与属性字段的名称⽆关
*/
public class UserService {
@Autowired
private UserDao userDao; // 默认通过类型(Class类型)查找bean对象 与属性字段
的名称⽆关
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void test() {
// 调⽤UserDao的⽅法
userDao.test();
}
}
2、属性可以提供set⽅法,也可以不提供set⽅法
/**
* @Autowired注解实现⾃动化注⼊
* 属性可以提供set⽅法,也可以不提供set⽅法
*/
public class UserService {
@Autowired
private UserDao userDao; // 不提供set⽅法
public void test() {
// 调⽤UserDao的⽅法
userDao.test();
}
}
3、 注解可以声明在属性级别 或 set⽅法级别
/**
* @Autowired注解实现⾃动化注⼊
* 注解可以声明在属性级别 或 set⽅法级别
*/
public class UserService {
private UserDao userDao;
@Autowired// 注解可以声明在set⽅法级别
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void test() {
// 调⽤UserDao的⽅法
userDao.test();
}
}
4、可以添加@Qualifier结合使⽤,通过value属性值查找bean对象(value属性值必须要设置,且值要与bean标签的id属性值对应)
/**
* @Autowired注解实现⾃动化注⼊
* 可以添加@Qualifier结合使⽤,通过value属性值查找bean对象
value属性值必须要设置,且值要与bean标签的id属性值对应
*/
public class UserService {
@Autowired
@Qualifier(value="userDao") // value属性值必须要设置,且值要与bean标签的id属
性值对应
private UserDao userDao;
public void test() {
userDao.test();
}
}
总结:
推荐使⽤@Resource 注解是属于J2EE的,减少了与Spring的耦合。