文章目录
Spring Bean的生命周期
Created with Raphaël 2.3.0 实例化Bean Bean属性赋值 检查Bean是否实现了Aware的相关接口,并且设置相关依赖 Bean后处理器before执行 检查Bean是否实现了InitializingBean的相关接口,并且设置相关依赖 初始化Bean Bean后处理器after执行 使用Bean 检查Bean是否实现了DisposableBean的相关接口,并且设置相关依赖 销毁Bean
生命周期扩展接口:
BeanNameAware、BeanClassLoaderAware、BeanFactoryAware、InitializingBean、DisposableBean、BeanPostProcessor
1、BeanNameAware
BeanNameAware
是一个在 Spring 框架中定义的接口。它是一个回调接口,允许被 Spring 容器管理的 Bean 在初始化过程中获取到自己的 Bean 名称。这对于需要基于 Bean 名称来执行某些特定逻辑的应用场景非常有用。
接口定义:
java
public interface BeanNameAware {
void setBeanName(String name);
}
setBeanName(String name)
方法会在 Spring 容器创建完 Bean 实例后调用,并传入该 Bean 的名称作为参数。
使用场景:
- 当 Bean 需要知道自己在容器中的名称时,可以实现此接口。例如,在日志记录、配置文件读取等方面可能需要使用 Bean 的名称。
示例代码 :
假设我们有一个名为 MyBean
的类,它实现了 BeanNameAware
接口:
java
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
public class MyBean implements BeanNameAware {
private String beanName;
@Override
public void setBeanName(String name) throws BeansException {
this.beanName = name;
System.out.println("Bean Name: " + name);
}
}
2、BeanClassLoaderAware
BeanClassLoaderAware
是 Spring 框架中的一个接口,它允许被 Spring 容器管理的 Bean 获得其ClassLoader(类加载器)。这在某些情况下是非常有用的,特别是当 Bean 需要进行类的动态加载或访问类路径资源时。
接口定义:
java
public interface BeanClassLoaderAware {
void setBeanClassLoader(ClassLoader classLoader);
}
setBeanClassLoader(ClassLoader classLoader)
方法会在 Spring 容器创建完 Bean 实例后调用,并传入该 Bean 的 ClassLoader 作为参数。
使用场景:
- 当 Bean 需要根据 ClassLoader 加载类或资源时,可以实现此接口。例如,如果你需要在运行时加载一些配置文件或动态生成的类,那么 BeanClassLoader 就会很有用。
示例代码 :
假设我们有一个名为 MyBean
的类,它实现了 BeanClassLoaderAware
接口:
java
import org.springframework.beans.factory.BeanClassLoaderAware;
public class MyBean implements BeanClassLoaderAware {
private ClassLoader classLoader;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
System.out.println("Bean ClassLoader: " + classLoader);
}
// 使用 classLoader 加载资源的方法
public void loadResource() {
try {
Class<?> clazz = classLoader.loadClass("com.example.MyDynamicClass");
// ... 进一步处理 ...
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
3、BeanFactoryAware
BeanFactoryAware
是 Spring 框架中的一个接口,它允许被 Spring 容器管理的 Bean 获得 BeanFactory
的引用。这对于需要直接与 Spring 容器交互的 Bean 来说非常有用。
接口定义:
java
public interface BeanFactoryAware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
setBeanFactory(BeanFactory beanFactory)
方法会在 Spring 容器创建完 Bean 实例后调用,并传入该 Bean 的 BeanFactory
作为参数。
使用场景:
- 当 Bean 需要直接从 Spring 容器中获取其他 Bean 的实例时,可以实现此接口。例如,如果一个 Bean 需要根据条件来决定是否注入另一个 Bean,或者需要在运行时动态地获取其他 Bean 的实例,那么
BeanFactory
就会很有用。
示例代码 :
假设我们有一个名为 MyBean
的类,它实现了 BeanFactoryAware
接口:
java
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
public class MyBean implements BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
System.out.println("BeanFactory: " + beanFactory);
}
// 使用 beanFactory 获取其他 Bean 的方法
public Object getAnotherBean(String beanName) {
return beanFactory.getBean(beanName);
}
}
4、InitializingBean
InitializingBean
是 Spring 框架中的一个接口,它提供了一种机制让 Bean 在初始化完成后执行一些额外的操作。实现这个接口的 Bean 可以定义一个 afterPropertiesSet()
方法,该方法将在所有的属性被设置之后调用。
接口定义:
java
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
afterPropertiesSet()
方法用于执行初始化操作。如果方法抛出异常,Spring 容器会捕获这些异常并适当地处理它们。
使用场景:
- 当 Bean 需要在所有属性被注入后执行一些初始化操作时,可以实现此接口。例如,验证配置、预加载数据、连接数据库等。
示例代码 :
假设我们有一个名为 MyBean
的类,它实现了 InitializingBean
接口:
java
import org.springframework.beans.factory.InitializingBean;
public class MyBean implements InitializingBean {
private String someProperty;
public void setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
@Override
public void afterPropertiesSet() throws Exception {
// 初始化操作
System.out.println("Initializing MyBean with property: " + someProperty);
// ... 更多初始化操作 ...
}
}
注意事项:
- 如果 Bean 同时实现了
InitializingBean
和定义了一个带有@PostConstruct
注解的方法,那么
@PostConstruct
标记的方法将优先于afterPropertiesSet()
方法执行。 - 如果 Bean 定义了
init-method
属性,那么该方法将优先于afterPropertiesSet()
方法执行。 - 如果 Bean 既实现了
InitializingBean
接口又定义了init-method
,那么init-method
将在afterPropertiesSet()
方法之后执行。
5、DisposableBean
DisposableBean
是 Spring 框架中的一个接口,它允许被 Spring 容器管理的 Bean 在容器销毁时执行一些清理工作。这对于释放资源(如关闭数据库连接、网络连接或其他需要显式关闭的资源)非常重要。
接口定义:
java
public interface DisposableBean {
void destroy() throws Exception;
}
destroy()
方法会在 Spring 容器销毁 Bean 之前调用。如果方法抛出异常,Spring 容器会捕获这些异常并适当地处理它们。
使用场景:
- 当 Bean 需要在容器销毁时执行一些清理操作时,可以实现此接口。例如,关闭数据库连接、释放文件句柄、断开网络连接等。
示例代码 :
假设我们有一个名为 MyBean
的类,它实现了 DisposableBean
接口:
java
import org.springframework.beans.factory.DisposableBean;
public class MyBean implements DisposableBean {
private Connection connection;
public void setConnection(Connection connection) {
this.connection = connection;
}
@Override
public void destroy() throws Exception {
if (connection != null) {
connection.close();
System.out.println("Connection closed.");
}
}
}
注意事项:
- 如果 Bean 同时实现了
DisposableBean
接口和定义了一个带有@PreDestroy
注解的方法,那么
@PreDestroy
标记的方法将优先于destroy()
方法执行。 - 如果 Bean 定义了
destroy-method
属性,那么该方法将优先于destroy()
方法执行。 - 如果 Bean 既实现了
DisposableBean
接口又定义了destroy-method
,那么destroy-method
将在destroy()
方法之后执行。
6、BeanPostProcessor
BeanPostProcessor
是 Spring 框架中的一个核心接口,它提供了在 Bean 初始化前后进行自定义处理的能力。实现 BeanPostProcessor
接口可以让开发者在 Spring 容器中添加自定义的逻辑,例如进行 AOP(面向切面编程)的织入、Bean 的属性修改等。
主要特点:
-
接口定义:
javapublic interface BeanPostProcessor { Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
postProcessBeforeInitialization(Object bean, String beanName)
:在 Bean 的初始化方法(如afterPropertiesSet()
或任何由init-method
指定的方法)被调用之前调用。postProcessAfterInitialization(Object bean, String beanName)
:在 Bean 的初始化方法被调用之后调用。
-
使用场景:
- 自动装配切点和通知(AOP)。
- 修改 Bean 的属性或替换整个 Bean。
- 执行通用的初始化或清理操作。
-
示例代码 :
假设我们有一个名为
MyBeanPostProcessor
的类,它实现了BeanPostProcessor
接口:javaimport org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("Bean '" + beanName + "' is about to be initialized."); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("Bean '" + beanName + "' has been initialized."); return bean; } }
注意事项:
- Spring 容器会在内部维护一个
BeanPostProcessor
列表,并按照声明顺序调用它们。 - 如果多个
BeanPostProcessor
被定义,它们会按声明顺序依次调用。 BeanPostProcessor
的实现类可能会改变传递给它的 Bean 对象。这意味着返回的对象可以是不同的类型或不同的实例。