由 【spring注解开发】1、快速体验IOC,给容器中注册组件 这一小节,我们已经把Bean的生命周期交由容器管理,我们可以自定义初始化和销毁的方法,当容器管理Bean进行到相应的生命周期的时候就会调用相应的方法。
1、两种指定初始化和销毁方法的方式
1.1、 @Bean指定的方式
在User类中创建init和destroy方法,
package com.xx.ioc.model;
public class User {
public User() {
System.out.println("---> user.constructor");
}
public void init() {
System.out.println("---> user.init");
}
public void destroy() {
System.out.println("---> user.destroy");
}
}
接下来我们使用@Bean的方式注册组件,
@Configuration // 这是一个配置类
public class UserConfig {
@Bean(initMethod = "init", destroyMethod = "destroy")
public User user() {
return new User();
}
}
现在在main方法中来创建以及关闭容器,观察可以看到,容器创建的时候会执行构造器以及指定的init方法,关闭容器之前会执行destroy方法。
public class Main {
public static void main(String[] args) {
// User user = new User();
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(UserConfig.class);
System.out.println("容器创建完成");
ctx.close();
System.out.println("容器已关闭");
}
}
/*打印:
---> user.constructor
---> user.init
容器创建完成
---> user.destroy
容器已关闭
*/
1.2、 实现InitializingBean和DisposableBean接口的方式
在InitializingBean源码可以看到,在设置完成Bean之后会调用afterPropertiesSet方法。
public interface InitializingBean {
/**
* Invoked by the containing {@code BeanFactory} after it has set all bean properties
* and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc.
* <p>This method allows the bean instance to perform validation of its overall
* configuration and final initialization when all bean properties have been set.
* @throws Exception in the event of misconfiguration (such as failure to set an
* essential property) or if initialization fails for any other reason
*/
void afterPropertiesSet() throws Exception;
}
DisposableBean接口中的destroy方法会在销毁Bean时调用。
public interface DisposableBean {
/**
* Invoked by the containing {@code BeanFactory} on destruction of a bean.
* @throws Exception in case of shutdown errors. Exceptions will get logged
* but not rethrown to allow other beans to release their resources as well.
*/
void destroy() throws Exception;
}
下面我们就让User类实现这两个接口,并实现其中的方法,
public class User implements InitializingBean, DisposableBean {
public User() {
System.out.println("---> user.constructor");
}
@Override
public void destroy() throws Exception {
System.out.println("---> user.destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("--> user.afterPropertiesSet");
}
}
在配置类中注册User,
@Configuration // 这是一个配置类
public class UserConfig {
@Bean
public User user() {
return new User();
}
}
接下来,就可以在main方法中获取这个user对象,观察输出可以看到容器创建的时候会实例化User对象,关闭容器的时候会先销毁User对象。
public class Main {
public static void main(String[] args) {
// User user = new User();
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(UserConfig.class);
System.out.println("容器创建完成");
ctx.close();
System.out.println("容器已关闭");
}
}
/*
---> user.constructor
--> user.afterPropertiesSet
容器创建完成
---> user.destroy
容器已关闭
*/
2、BeanPostProcessor后置处理器
BeanPostProcessor,在bean初始化前后进行一些处理工作。BeanPostProcessor接口中有两个方法,
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
- postProcessBeforeInitialization 初始化之前进行一些后置工作
- postProcessAfterInitialization 初始化之后进行后置工作
接上面的例子,我们就创建MyBeanPostProcessor实现BeanPostProcessor接口,并实现其中的方法,并用@Component注册到容器中去,
package com.xx.ioc.config;
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("--->postProcessBeforeInitialization,--->bean "+ bean + ",--->beanName " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("--->postProcessAfterInitialization,--->bean "+ bean + ",--->beanName " + beanName);
return bean;
}
}
让我们的UserConfig类可以扫描到MyBeanPostProcessor,
package com.xx.ioc.config;
import com.xx.ioc.model.User;
@Configuration // 这是一个配置类
@ComponentScan("com.xx.ioc.config")
public class UserConfig {
@Bean
public User user() {
return new User();
}
}
最后,在main方法中我们获取user实列,我们可以观察到在设置user前后分别执行了postProcessBeforeInitialization和postProcessAfterInitialization方法,
public class Main {
public static void main(String[] args) {
// User user = new User();
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(UserConfig.class);
System.out.println("容器创建完成");
ctx.close();
System.out.println("容器已关闭");
}
}
/*打印:
--->postProcessBeforeInitialization,--->bean com.xx.ioc.config.UserConfig$$EnhancerBySpringCGLIB$$86643ebe@f0f2775,--->beanName userConfig
--->postProcessAfterInitialization,--->bean com.xx.ioc.config.UserConfig$$EnhancerBySpringCGLIB$$86643ebe@f0f2775,--->beanName userConfig
---> user.constructor
--->postProcessBeforeInitialization,--->bean com.xx.ioc.model.User@29ba4338,--->beanName user
--> user.afterPropertiesSet
--->postProcessAfterInitialization,--->bean com.xx.ioc.model.User@29ba4338,--->beanName user
容器创建完成
---> user.destroy
容器已关闭
*/
可以看到,MyBeanPostProcessor不仅作用在了User类上,只要是注册到容器中的组件都起了作用。