【Spring入门-01】Bean
文章目录
Spring Bean
作用域
-
singleton
:一个 Bean 容器中只存在一个实例(Spring 默认作用域) -
prototype
:每次注入或者通过 Spring 应用上下文获取时都会创建一个单独的实例 -
request
:每个 request 请求都会创建一个单独的实例 -
session
:每个 session 都会创建一个单独的实例 -
application
:每个 servletContext 都会创建一个单独的实例 -
websocket
:每个 websocket 都会创建一个单独的实例 -
simpleThreadScope
:每个线程都会创建一个单独的实例
singleton
使用 @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
注解标注 Bean 的作用域为 singleton
,则每次注入的 bean 都是同一个实例。
- JavaConfig
@Configuration
public class ScopeBeanConfig {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public SingletonBean singletonBean() {
return new SingletonBean();
}
}
public class SingletonBean {
}
- XML 配置
<bean class="SingletonBean" scope="singleton"/>
prototype
使用 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
注解标注 Bean 的作用域为 prototype
,则每次注入或从 Spring 应用上下文获取的 bean 都会创建一个新的实例。
- JavaConfig
@Configuration
public class ScopeBeanConfig {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public PrototypeBean prototypeBean() {
return new PrototypeBean();
}
}
public class PrototypeBean {
}
- XML 配置
<bean class="PrototypeBean" scope="prototype"/>
request
使用 @RequestScope
注解标注 Bean 的作用域为 request
,则每次 request 请求的 bean 都会创建一个新的实例。
- JavaConfig
@Configuration
public class ScopeBeanConfig {
@Bean
@RequestScope
public RequestBean requestBean() {
return new RequestBean();
}
}
public class RequestBean {
}
- XML 配置
<bean class="RequestBean" scope="request"/>
session
使用 @SessionScope
注解标注 Bean 的作用域为 session
,则会为每个 session 创建一个新的 bean 实例。
- JavaConfig
@Configuration
public class ScopeBeanConfig {
@Bean
@SessionScope
public SessionBean sessionBean() {
return new SessionBean();
}
}
public class SessionBean {
}
- XML 配置
<bean class="SessionBean" scope="session"/>
作用域代理
当 request/session
作用域的 bean(cart) 注入到 singleton
作用域的 bean(storeService) 时
@Configuration
public class ScopeBeanConfig {
@Bean
@SessionScope(proxyMode = ScopedProxyMode.INTERFACES)
public Cart cart(){
return new ShoppingCart();
}
@Bean
public StoreService storeService(){
return new StoreServiceImpl();
}
}
public interface Cart {
}
public class ShoppingCart implements Cart {
}
public interface StoreService {
void add();
}
public class StoreServiceImpl implements StoreService {
@Autowired
private Cart cart;
@Override
public void add() {
System.out.println(cart.toString());
}
}
singleton
作用域的 StoreService 在 Spring 应用上下文加载时实例化,同时试图将 Cart 构造注入。但是 session
作用域的 Cart 直到创建会话 session 后才会实例化。因此,Spring 会注入一个 Cart 的代理(暴露 Cart 中定义的方法),当 StoreService 调用 Cart 的方法时,代理会对其进行懒解析并调用委托给 session
作用域内真正的 Cart 。
通过 proxyMode
属性指定代理方式:
-
ScopedProxyMode.INTERFACES
:基于 JDK 动态接口代理 -
ScopedProxyMode.TARGET_CLASS
:基于 CGLib 代理
懒加载
Spring 容器会在创建容器时提前初始化 singleton
作用域的 Bean。但是如果 Bean 被标注了 lazy-init="true"
,则该 Bean 只有在其被需要的时候才会被初始化。
懒加载只对 singleton
作用域的 Bean 有效。
优点:节省资源
缺点:导致操作的响应时间增加
生命周期
初始化
如果需要在 Bean 实例化之后执行逻辑:
- 使用 init-method
public class Bean {
public void init() {
// To do
}
}
通过 XML 配置
<bean class="Bean" init-method="init"/>
通过 JavaConfig
@Bean(initMethod = "init")
public Bean bean() {
return new Bean();
}
- 让 Bean 实现
org.springframework.beans.factory. InitializingBean
接口,覆盖afterPropertiesSet
方法
public class Bean implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
// To do
}
}
销毁
如果需要在 Bean 销毁之前执行逻辑:
- 使用 destroy-method
public class Bean {
public void destroy() {
//To do
}
}
通过 XML 配置
<bean class="Bean" init-method="destroy"/>
通过 JavaConfig
@Bean(destroyMethod = "destroy")
public Bean bean() {
return new Bean();
}
- 让 Bean 实现
org.springframework.beans.factory.DisposableBean
接口,覆盖destroy
方法
public class Bean implements DisposableBean {
@Override
public void destroy() throws Exception {
//To do
}
}
配置全局默认初始化、销毁方法
<?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"
default-init-method="init" default-destroy-method="destroy">
</beans>
Bean 后置处理器
如果想在 Spring IoC 容器完成 Bean 实例化、配置及初始化方法前后添加逻辑处理,可通过实现 BeanPostProcessor
接口定义的回调方法。此外,还可以通过实现 Ordered 接口提供的 order 属性来控制这些实现了 BeanPostProcessor
接口 Bean 后置处理器的执行顺序。
@Component
public class PostProcessor1 implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean后置处理器1 before initialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean后置处理器1 after initialization");
return bean;
}
@Override
public int getOrder() {
return 1;
}
}
@Component
public class PostProcessor2 implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean后置处理器2 before initialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean后置处理器2 after initialization");
return bean;
}
@Override
public int getOrder() {
return 2;
}
}
<bean class="PostProcessor1"/>
<bean class="PostProcessor2"/>
参考
上一篇: Spring入门_01
下一篇: AWK 用法总结