文章目录
收藏这三篇笔记,完整回顾Spring常见问题及使用方式速查:
0. 基本概念
- 控制反转(IoC):被调用者的实例不再由调用者创建,而是由 Spring 容器创建,这称为控制反转。
- 依赖注入(DI):Spring 容器在创建被调用者的实例时,会自动将调用者需要的对象实例注入给调用者,这样,调用者通过 Spring 容器获得被调用者实例,这称为依赖注入。
文档、JAR包:官方仓库地址。
1. 示例pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>test<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>test<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>1.0-SNAPSHOT<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependencies</span><span class="token punctuation">></span></span>
<span class="token comment"><!-- spring --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-core<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>5.2.6.RELEASE<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-beans<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>5.2.6.RELEASE<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-context<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>5.2.6.RELEASE<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-context-support<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>5.2.6.RELEASE<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.springframework<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>spring-expression<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>5.2.6.RELEASE<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span>
<span class="token comment"><!-- lombok --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>org.projectlombok<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>lombok<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>1.16.18<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>scope</span><span class="token punctuation">></span></span>provided<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>scope</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependencies</span><span class="token punctuation">></span></span>
</project>
2. IOC容器
二者相比,前者功能简单且没有初始化自检。
2.1 BeanFactory(不常用)
Resource resource = new ClassPathResource("ApplicationContext.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
beanFactory.getBean("$BeanName");
2.2 ApplicationContext(示例)
ApplicationContext.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>bean</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>service0<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Service<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>constructor-arg</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>java.lang.String<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>service0:name<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>bean</span><span class="token punctuation">></span></span>
<span class="token comment"><!-- 构造标签详见下 --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>bean</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>dao0<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>DAO<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>constructor-arg</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>id<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>java.lang.Integer<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>7<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>constructor-arg</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>java.lang.String<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>dao0<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>constructor-arg</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>service<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Service<span class="token punctuation">"</span></span> <span class="token attr-name">ref</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>service0<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span> <span class="token comment"><!-- 实例依赖--></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>bean</span><span class="token punctuation">></span></span>
</beans>
Service.java
:
@Data // 使用了 lombok
@AllArgsConstructor
public class Service {
private String name;
}
DAO.java
:
@Data
@AllArgsConstructor
public class DAO {
private Integer id;
private String name;
private Service service; // 依赖Service,采用`ref`
}
测试代码:
public class Main {
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
DAO a = (DAO)context.getBean("dao0");
System.out.println(a);
}
}
目录结构为:
2.3 通过注解进行装配
通过注解进行装配,编写方便、无需写xml标签文件,但若有更改需要重编译。
2.3.1 常用注解
@Component
:可以使用此注解描述 Spring 中的 Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应类上即可;将会将其实例化和注入依赖并加入IoC容器。@Repository
:用于将数据访问层(DAO层)的类标识为 Spring 中的 Bean,其功能与@Component
相同。@Service
:通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与@Component
相同。@Controller
:通常作用在控制层(如 Struts2 的 Action),用于将控制层的类标识为 Spring 中的 Bean,其功能与@Component
相同。@Autowired
:用于对 Bean 的属性变量、属性的 Set 方法及构造函数进行标注,配合对应的注解处理器完成 Bean 的自动配置工作。默认按照 Bean 的类型进行装配。@Resource
:其作用与 Autowired 一样。其区别在于@Autowired
默认按照 Bean 类型装配,而@Resource
默认按照 Bean 实例名称进行装配。@Qualifier
:与@Autowired
注解配合使用,会将默认的按 Bean 类型装配修改为按 Bean 的实例名称装配,Bean 的实例名称由@Qualifier
注解的参数指定。
附 · 使用JacaConfig类配置Bean所用到的注解:
@Configuation
等价于<beans></beans>
,不可用于标注final
、匿名类,必须为静态类。@Bean
等价于<bean></bean>
。@ComponentScan
等价于<context:component-scan base-package="com.dxz.demo"/>
。
2.3.2 示例:使用注解装配的MVC
目录结构:
此处可以选择构建一个配置类以取代 ApplicationContext.xml
:
@Configuration // 该注解同样也需要被扫描到,因此同样要在xml文件中进行配置
// @ComponentScan("MVC") // 等价于<context:component-scan base-package="MVC"/> //由于目录结构中该配置类与MVC同包,会被xml配置直接扫描到,因此此处不需要。
public class SpringConfiguration {
// 等价于
// <bean id="user0" class="xxx.User">
// <constructor-arg name="id" type="java.lang.Integer" value="0"></constructor-arg>
// <constructor-arg name="name" type="java.lang.String" value="Jack"></constructor-arg>
// </bean>
@Bean(name = "user0")
public User UserBeanJack(){
return new User(0, "Jack");
}
}
构建一个控制器:
@Controller
public class UserController {
@Resource // 此处使用Resource,默认采用首字母小写的形式去找到类, 等价于 getBean("userService")
private UserService userService;
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">acceptRequest</span><span class="token punctuation">(</span>ApplicationContext context<span class="token punctuation">,</span> Object request<span class="token punctuation">)</span><span class="token punctuation">{
<!-- --></span>
System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Accept request."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
User user <span class="token operator">=</span> <span class="token punctuation">(</span>User<span class="token punctuation">)</span>context<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span><span class="token string">"user0"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 假设根据Request构建Model</span>
System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Controller find user: "</span> <span class="token operator">+</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>userService<span class="token punctuation">.</span><span class="token function">service</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 找到Model对应的业务</span>
System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"MVC Controller Over."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
构建Model层的各个组件:,首先是业务逻辑:
@Service("userService") // 默认是类名首字母小写, 等价于 <bean id="userService" class="xxx.UserService"/>
public class UserService {
private UserDao userDao;
<span class="token annotation punctuation">@Autowired</span> <span class="token comment">// 此处使用自动装配的形式</span>
<span class="token keyword">public</span> <span class="token function">UserService</span><span class="token punctuation">(</span>UserDao userDao<span class="token punctuation">)</span><span class="token punctuation">{
<!-- --></span>
<span class="token keyword">this</span><span class="token punctuation">.</span>userDao <span class="token operator">=</span> userDao<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">service</span><span class="token punctuation">(</span>User user<span class="token punctuation">)</span><span class="token punctuation">{
<!-- --></span>
System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"MVC Service sth. with "</span> <span class="token operator">+</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>userDao<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"MVC Service Over."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
数据持久层:
@Repository("userDao") // 等价于 <bean id="userDao" class="xxx.UserDao"/>
public class UserDao {
public void save(User user){
System.out.println("数据库已保存" + user);
}
}
一个POJO类:
@Data // 使用了lombok简化代码编写
@AllArgsConstructor
public class User {
private Integer id;
private String name;
}
最后,还需要让Spring扫描到这些注解:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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">
<!-- 增加第3, 8, 9行-->
<context:component-scan base-package="MVC"/>
</beans>
测试:
public class Main {
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span><span class="token punctuation">{
<!-- --></span>
<span class="token keyword">final</span> ApplicationContext context <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ClassPathXmlApplicationContext</span><span class="token punctuation">(</span><span class="token string">"ApplicationContext.xml"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
UserController userController <span class="token operator">=</span> <span class="token punctuation">(</span>UserController<span class="token punctuation">)</span>context<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span><span class="token string">"userController"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 注意不能用 UserController userController = new UserController();</span>
userController<span class="token punctuation">.</span><span class="token function">acceptRequest</span><span class="token punctuation">(</span>context<span class="token punctuation">,</span> null<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
/打印结果如下: Accept request. Controller find user: User(id=0, name=Jack) MVC Service sth. with User(id=0, name=Jack) 数据库已保存User(id=0, name=Jack) MVC Service Over. MVC Controller Over./
- 需要注意的是,所有的实例都要从IoC容器里获取,自行new出来的实例不会被Spring注入,会导致Null异常。
2.3.3 示例所使用的流程图
2.4 往容器内配置Bean的三种方式
- 使用xml进行配置,bean的名字为
id
字段。 - 使用JavaConfig进行配置(
@Configuration
),默认bean的名字为@Bean
所标注的方法名。 - 使用注解进行配置,默认Bean的名字为类名(首字母小写)。
2.5 @Autowired 和 @Resource 的区别
- 前者默认按类型装配,当容器内存在多种同一类型的Bean时,需要使用
@Qualifier(value = "$BeanName")
才可以找到被注入的对象。 - 后者在不指定
name
字段时,也是以同一类型的Bean进行注入,若存在多个同类型对象,会报错;当指定name
字段时等同于getBean("$BeanName")
(某些框架中,找不到会再根据类型寻找)。 - 二者都可以标注在
setter()
或构造器方法上;@Autowired
不被推荐在字段上直接标注(缺点见下文)。
2.5.1 注入方式及字段注入的缺点
对于二者,注入方式都有三种:构造器注入、setter注入、field注入,区别如下:
public class UserController {
@Autowired // field注入,也称为反射注入或字段注入,对访问级别无要求
private UserService userService;
<span class="token annotation punctuation">@Autowired</span> <span class="token comment">// 构造器注入(需要为public) 适用于强制依赖项</span>
<span class="token keyword">public</span> <span class="token function">UserController</span><span class="token punctuation">(</span>UserService userService<span class="token punctuation">)</span><span class="token punctuation">{
<!-- --></span>
<span class="token keyword">this</span><span class="token punctuation">.</span>userService <span class="token operator">=</span> userService<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Autowired</span> <span class="token comment">// setter注入(需要为public) 适用于可选依赖项</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setUserService</span><span class="token punctuation">(</span>UserService userService<span class="token punctuation">)</span><span class="token punctuation">{
<!-- --></span>
<span class="token keyword">this</span><span class="token punctuation">.</span>userService <span class="token operator">=</span> userService<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
使用字段注入,其最大缺点为:
- 类会和Spring强耦合,由于无构造器或setter方法,无法在容器外使用。
- 无法使用属性注入的方式构建不可变对象。
- 同第一小点,在测试时无法脱离容器进行测试,即 new 出来的 Mock 对象无法被引入测试单元。
- 强依赖和可选依赖都被隐藏,无法区分,违背单一职责原则。
3. Bean的常见概念
3.1 Bean的常用属性
属性名称 | 描述 |
---|---|
id | 是一个 Bean 的唯一标识符,Spring 容器对 Bean 的配置和管理都通过该属性完成 |
name | Spring 容器同样可以通过此属性对容器中的 Bean 进行配置和管理,name 属性中可以为 Bean 指定多个名称,每个名称之间用逗号或分号隔开 |
class | 该属性指定了 Bean 的具体实现类,它必须是一个完整的类名,使用类的全限定名 |
scope | 用于设定 Bean 实例的作用域,其属性值有 singleton(单例)、prototype(原型)、request、session 和 global Session。其【默认值】是 singleton。 |
property | 元素的子元素,用于调用 Bean 实例中的 Set 方法完成属性赋值,从而完成依赖注入。该元素的 name 属性指定 Bean 实例中的相应属性名 |
constructor-arg | 元素的子元素,可以使用此元素传入构造参数进行实例化。该元素的 index 属性指定构造参数的序号(从 0 开始),type 属性指定构造参数的类型 |
constructor-arg:name/index | 标定一个bean的属性名称/构造函数的第index个参数,用于初始化实例 |
ref/value | 和 等元素的子元素,用于直接指定一个引用/常量值;亦可作为初始化时注入集合类元素的标签 |
list | 用于封装 List 或数组类型的依赖注入 |
set | 用于封装 Set 或数组类型的依赖注入 |
map | 用于封装 Map 或数组类型的依赖注入 |
entry | |
factory-bean | 当class是一个工厂类时,指定其作为工厂 |
factory-method | 当class是一个工厂类时,使用该标签标注的静态方法(或若已指定一个factory-bean标注的实例)得到实例 |
autowire | 是否自动装配,详见下文表格 |
3.1.1 自动装配
属性取值 | 描述 |
---|---|
byName | 根据 Property 的 name 自动装配,如果一个 Bean 的 name 和另一个 Bean 中的 Property 的 name 相同,则自动装配这个 Bean 到 Property 中。 |
byType | 根据 Property 的数据类型(Type)自动装配,如果一个 Bean 的数据类型兼容另一个 Bean 中 Property 的数据类型,则自动装配。 |
constructor | 根据构造方法的参数的数据类型,进行 byType 模式的自动装配。 |
autodetect | 如果发现默认的构造方法,则用 constructor 模式,否则用 byType 模式。 |
no | 【默认】情况下,不使用自动装配,Bean 依赖必须通过 ref 元素定义。 |
3.2 Bean的作用域
Spring 容器在初始化一个 Bean 的实例时,同时会指定该实例的作用域。Spring3 为 Bean 定义了五种作用域,具体如下。
singleton
:单例模式,使用 singleton 定义的 Bean 在 Spring 容器中只有一个实例,这也是 Bean 【默认】的作用域。prototype
:原型模式,每次通过 Spring 容器获取 prototype 定义的 Bean 时,容器都将创建一个新的 Bean 实例。request
:在一次 HTTP 请求中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Request 内有效。session
:在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Session 内有效。global Session
:在一个全局的 HTTP Session 中,容器会返回该 Bean 的同一个实例。该作用域仅在使用 portlet context 时有效。
3.3 Bean的生命周期
- 根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean,包含以下四个预处理项目:
ResouceLoader
加载配置信息;BeanDefintionReader
解析配置信息,生成若干个BeanDefintion
;BeanDefintion
由BeanDefintionRegistry
管理起来;BeanFactoryPostProcessor
对配置信息进行加工(也就是处理配置的信息,一般通过PropertyPlaceholderConfigurer
来实现);
- 利用依赖注入完成 Bean 中所有属性值的配置注入。
- 如果 Bean 实现了
BeanNameAware
接口,则 Spring 调用 Bean 的setBeanName()
方法传入当前 Bean 的id
值。 - 如果 Bean 实现了
BeanFactoryAware
接口,则 Spring 调用setBeanFactory()
方法传入当前工厂实例的引用。 - 如果 Bean 实现了
ApplicationContextAware
接口,则 Spring 调用setApplicationContext()
方法传入当前ApplicationContext
实例的引用。 - 如果
BeanPostProcessor
(BBP) 和 Bean 关联,则 Spring 将调用该接口的预初始化方法postProcessBeforeInitialzation()
对 Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的。 - 如果 Bean 实现了
InitializingBean
接口,则 Spring 将调用afterPropertiesSet()
方法。 - 如果在配置文件中通过
init-method
属性指定了初始化方法,则调用该初始化方法。 - 如果
BeanPostProcessor
和 Bean 关联,则 Spring 将调用该接口的初始化方法postProcessAfterInitialization()
。此时,Bean 已经可以被应用系统使用了。 - 如果在
<bean>
中指定了该 Bean 的作用范围为scope="singleton"
,则将该 Bean 放入 Spring IoC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在<bean>
中指定了该 Bean 的作用范围为scope="prototype"
,则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean。 - 如果 Bean 实现了
DisposableBean
接口,则 Spring 会调用destory()
方法将 Spring 中的 Bean 销毁;如果在配置文件中通过destory-method
属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁。