注解配置和 xml 配置要实现的功能都是一样的,都是要降低程序间的耦合。只是配置的形式不一样。
Spring 基于注解的 IoC 详解
- 我们先来看看之前的XML的配置:
<bean id="accountService" class="com.cz.service.impl.AccountServiceImpl" scope="" init-method="" destroy-method="">
<property name="" value="" ref=""></property>
</bean>
上面的XML配置中有多个标签和属性,至于这些标签和属性的作用是啥,大家可以去看看上一篇文章。传送门
- 接下来,Spring基于注解的IoC也分为四类:
- 用于创建对象的:
- 他们的作用就和在XML配置文件中编写一个
<bean>
标签的功能是一样的- 用于注入数据:
- 他们的作用就和在XML配置文件中的
<bean>
标签中写一个<property>
标签的作用是一样的。- 用于改变作用范围:
- 他们的作用就和在
<baen>
标签中使用<scope>
标签的作用是一样的。- 和生命周期相关:
- 他们的作用就和在
<bean>
标签中使用init-method
和destroy-method
的作用是一样的。
- 如果要使用注解的话,首先需要在配置文件中导入新的命名空间,并且指定要扫描的包。
<?xml version="1.0" encoding="UTF-8"?>
<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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--告知spring在创建容器时要扫描的包,配置所需要的标签不是在beans的约束中,而是一个名称为context名称空间和约束中-->
<context:component-scan base-package="com.cz"></context:component-scan>
</beans>
用于创建对象的注解
相当于:<bean id="" class="">
@Component 注解
- 作用
- 用于把当前类对象存入 Spring 容器中
- 属性
value
: 用于指定 Bean 的唯一标识 (Id)。如果没有写,默认值是当前类名,且首字母小写
- 除了
@Component
注解外,还有三个衍生注解也是用于创建对象,属性与@Component
一样,见下表:
注解名称 | 作用 |
---|---|
@Controller | 表现层 |
@Service | 业务层 |
@Repository | 持久层 |
他们三个的作用跟属性跟@Repository是一模一样的。这三个注解是 Spring 框架为我们提供明确的三层使用的注解,使我们的三层对象更加清晰。
细节:如果注解中有且只有一个属性要赋值时,且名称是 value,value 在赋值是可以不写。
package com.cz.service.impl;
import com.cz.dao.AccountDao;
import com.cz.dao.impl.AccountDaoImpl;
import com.cz.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
/**
* 账户的业务层实现类
*/
@Service(value = "accountService")
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public AccountServiceImpl(){
System.out.println("对象创建了");
}
public void saveAccount(){
accountDao.saveAccount();
System.out.println("service中的saveAccount方法执行了");
}
}
用于注入数据的注解
相当于:<property name=" " ref=" "> <property name="" value="">
@Autowired注解
- 作用
- 自动按照类型注入(By Type)
- 容器首先用变量的类型进行查找,如果容器中有
唯一一个 Bean 的类型匹配
,那么就直接注入;如果容器中没有任何 Bean的类型与要注入的变量类型匹配
,那么就报错;如果容器中有多个 Bean 的类型匹配
,那么容器就会以变量的名称作为 Bean的id进行查找
,找到匹配的则注入,未找到则报错。
- 出现位置
- 变量或者方法上
- 细节
- 当使用注解来注入属性时,
set 方法可以省略
- 当使用注解来注入属性时,
/**
- 账户的业务层实现类
*/
@Service(value = "accountService")
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao = null;
//......
对于上面的注解大家可以看看下图:
@Qualifier 注解
-
作用
- 在
按照类型注入的基础之上再按照名称注入
。它在给类成员注入时不能单独使用,必须和 @Autowired``一起使用
。但是在给方法参数注入时可以单独使用。
- 在
-
属性
-value
: 用于指定注入 Bean 的唯一标识 (Id)
/**
- 账户的业务层实现类
*/
@Service(value = "accountService")
public class AccountServiceImpl implements AccountService {
@Autowired
@Qualifier("accountDao")
private AccountDao accountDao = null;
//.....
@Resource 注解
-
作用
- 自动按照
名称注入(By Name)
,直接按照 Bean 的 Id 进行注入,它可以独立使用。
- 自动按照
-
属性
name
: 指定注入 Bean 的 id
/**
* 账户的业务层实现类
*/
@Service(value = "accountService")
public class AccountServiceImpl implements AccountService {
// @Autowired
// @Qualifier("accountDao")
@Resource(name = "accountDao")
private AccountDao accountDao = null;
以上三个注解都只能注入其他 Bean 类型的数据,而基本类型和 String 类型需要使用下面注解,另外,集合类型的注入只能通过XML来实现。
@Value 注解
- 作用
- 注入
基本类型和 String 类型数据
- 注入
- 属性
value
: 用于指定数据的值。它可以使用 Spring 中的 SpEL( Spring 的 el 表达式,写法:${表达式})
用于改变作用范围的
相当于:<bean id="" class="" scope="">
@Scope 注解
- 作用
- 指定 Bean 的作用范围
- 属性
value
: 指定范围的取值。常用取值为singleton、prototype
和生命周期有关
相当于:<bean id="" class="" init-method="" destroy-method="" />
@PreDestroy 注解
- 作用
- 用于指定销毁方法
PostConstruct 注解
- 作用
- 用于指定初始化方法
@PostConstruct
public void init() {
System.out.println("初始化方法执行了");
}
@PreDestroy
public void destroy() {
System.out.println("销毁方法执行了");
}
XML 和 注解方式的比较
- 注解的优势
- 配置简单,维护方便
- XML 的优势
- 修改时无需修改源码,不涉及重新编译和部署
Spring 管理 Bean 方式的比较:
基于 XML 配置 | 基于注解配置 | |
---|---|---|
Bean 定义 | <bean id = "..." class = "..." /> | @Component、@Controller、@Service、@Repository |
Bean 名称 | 通过id 或者 name 属性指定 | @Component("user") |
Bean 注入 | 通过<property> 或者 <constructor-arg> 标签注入 | @Autowired、@Qualifier、@Resource |
Bean 作用范围 | 通过scope 属性指定 | @Scope |
Bean 生命周期 | 通过 init-method 或者destroy-method 属性指定初始化和销毁方法 | @PostConstruct、@PreDestroy |
Bean 适合场景 | Bean 来自于第三方,无法修改源码 | Bean 的实现类由自己开发 |
Spring基于注解的IoC到这就讲完了,接下来会同一个案例来看看XML方式实现和注解方式实现的差别。