目录
[1.1 属性注入的优缺点分析](#1.1 属性注入的优缺点分析)
[2.1 Setter注入优缺点分析](#2.1 Setter注入优缺点分析)
[3.1 构造注入的优缺点](#3.1 构造注入的优缺点)
前言
在之前我们就已经了解过了Spring依赖注入的方式,但是前面所说的方式是通过配置文件的方式去进行依赖注入的,我们说配置文件的方式是比较麻烦的,所以在这里将使用注解的方式进行依赖注入。在Spring中使用注解进行依赖注入主要有3种方式:属性注入、Setter注入、构造方法注入。 在使用之前先介绍两种常用的注解**@Autowired、@Resource**下面一起来看
一、属性注入
属性注入是后面开发过程中使用最多的一种方式,即在属性中直接添加注解进而完成注解的效果。
首先创建一个UserDao类,为这个类添加注解(表示将对象存储在Spring中),这里的这个类是与数据库交互的
java
@Repository
public class UserDao {
public void login() {
System.out.println("---数据库核心操作---");
}
}
创建一个UserService类调用UserDao,这里就需要在UserService类中创建一个userDao对象,进而使用这个对象来调用其核心方法。以往使用的是配置文件的Bean标签的方式,现在只需要一个简单的注解就可以完成这个这个繁琐的过程了
XML
<bean id="userDao" class="com.gl.demo.dao.UserDao"/>
<bean id="userService1" class="com.gl.demo.service.UserService1">
<property name="userDao">
<ref bean="userDao"/>
</property>
</bean>
java
@Service
public class UserService1 {
// 使用注解对这个userDao对象进行注入
@Autowired
private UserDao userDao;
public void login() {
userDao.login();
}
}
java
@Test
public void test1() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
UserService1 userService = ctx.getBean("userService1", UserService1.class);
userService.login();
}
通过上述操作我们发现注解的属性注入确实方便了不少,但是属性注入的方式也是存在缺点的
1.1 属性注入的优缺点分析
优点:
- 使用方便,只需要变量上面加一个@Autowired即可
- 代码简洁,可读性高
缺点:
- 无法为final修饰的变量进行注入
- 通用性差,无法移植到非IO C容器中使用
- 不符合单一设计原则
二、Setter注入
这里的Setter注入也就是为这个变量添加一个setter方法,这里添加注解就是添加在setter方法上了,由于这里的测试方法都是一样的,所以这里就不再演示了
java
@Service
public class UserService2 {
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void login() {
System.out.println("Setter注入");
userDao.login();
}
}
2.1 Setter注入优缺点分析
优点:
- 符合单一设计原则
缺点:
- 不能给final修饰的变量注入
- 注入的对象可以被修改,由于是setter方法所以都能调用
三、构造方法注入
构造方法顾名思义就是,使用构造方法的方法为变量注入,将注解添加在构造方法上即可
java
@Service
public class UserService3 {
private UserDao userDao;
@Autowired
public UserService3(UserDao userDao) {
this.userDao = userDao;
}
public void login() {
System.out.println("构造注入");
userDao.login();
}
}
3.1 构造注入的优缺点
优点:
- 可以为final修饰的变量进行注入
- 不能被修改,由于构造方法只会被加载一次,所以不能被修改
- 通用性更好,在非IOC容器也能够使用
- 完全初始化,构造方法会在对象创建之前执行,所以会被完全初始化
缺点:
- 其实这个是官方推荐的方法,并没有什么明显的缺点,要说缺点的话就是没有属性注入简洁
四、@Qualifier注解
在介绍了**@Autowired** 注解进行注入之后,为什么还要有一个**@Resource** 注解进行注入呢?接下来看一个案例,我们使用**@Bean** 注解将同一个对象注入Spring两次,那么再通过**@Autowired**注解进行注入会发生什么呢?
首先创建一个User 类,再创建一个Users类往Spring中注入两个相同的对象
java
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
这里使用**@Bean**注解将同一个对象再Spring中创建两次
java
@Component
public class Users {
@Bean
public User user1() {
User user = new User();
user.setName("张三");
return user;
}
@Bean
public User user2() {
User user = new User();
user.setName("李四");
return user;
}
}
通过**@Autowired**进行依赖注入,一般情况下这里的注入是没有问题的,但是在Spring中有两个相同的对象。这样获取就会报错
java
@Controller
public class UserController {
@Autowired
private User user;
public void test() {
System.out.println(user);
}
}
java
@Test
public void test() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
UserController users = ctx.getBean("userController", UserController.class);
users.test();
}
这里的报错信息大概就是,找到了两个user对象分别是user1和user2,不知道你需要的是哪一个
这里的解决方法就是引入一个新的注解**@Qualifier** 来限制注入的对象是哪一个。(在**@Bean** 注解中方法名就是创建对象的id当然也可以在**@Bean注解** 中自定义id)同理,如果**@Qualifier**中是user2则打印的是"李四"
java
@Controller
public class UserController {
@Autowired
@Qualifier("user1")
private User user;
public void test() {
System.out.println(user);
}
}
五、@Resource注解
通过上面的案例我们发现使用两个注解解决问题还是有点麻烦,那么还有什么解决办法呢?这里使用JDK提供的**@Resource** 注解来解决这个问题。那么为什么不直接在**@Autowired** 注解中添加类限定名呢?那是因为**@Autowired**没有这个功能,这里我们查看源码也可以发现。这里的这个参数表示注入的时候这个Bean是否存在
java
@Controller
public class UserController {
//@Autowired
//@Qualifier("user1")
@Resource(name = "user2")
private User user1;
public void test() {
System.out.println(user1);
}
}
最后使用**@Resource**注解的时候也是可以实现注入功能的
六、@Resource注解与@Autowired注解的区别
- @Resource是Java自带的,@Autowired是Spring提供的的
- 相比于@Autowired来说@Resource支持更多的参数设置,例如name等
- @Autowired支持三种注入方式,但是@Resource不支持构造方法注入