IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring高级特性(3)----后置处理器及SpringBean的生命周期 -> 正文阅读

[Java知识库]Spring高级特性(3)----后置处理器及SpringBean的生命周期

Spring提供了两种后处理bean的扩展接口,分别为 BeanPostProcessor 和BeanFactoryPostProcessor,两者在使用上是有所区别的。工厂在前,bean对象在后。在BeanFactory初始化之后可以使用BeanFactoryPostProcessor进行后置处理做?些事情,在Bean对象实例化(并不是Bean的整个生命周期完成)之后可以使用BeanPostProcessor进行后置处理做?些事情。
注意:对象不一定是springbean,但springbean?定是个对象

(1)BeanPostProcessor

BeanPostProcessor是针对Bean级别的处理,可以针对某个具体的Bean。该接?提供了两个方法,分别在Bean的初始化方法前和初始化方法后执行,具体这个初始化方法指的是什么方法,类似我们在定义bean时,xml中定义的init-method所指定的方法。

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;
	}
}

定义?个类实现了BeanPostProcessor,默认是会对整个Spring容器中所有的bean进?处理。如果要对具体的某个bean处理,可以通过方法的形参进行判断,两个类型参数分别为Object和String,第?个参数是每个bean的实例,第?个参数是每个bean的name或者id属性的值。所以我们可以通过第?个参数,来判断我们将要处理的具体的bean。如下图,我们想要对lazyBean对象在初始化前后进行处理,这里的初始化就包括init-method属性中指定的initMethod方法。
注意:处理是发生在Spring容器的实例化和依赖注入之后。

<bean id="lazyBean" class="com.nanmao.LazyBean" init-method="initMethod" destroy-method="destroyMethod"/>
/**
 * 拦截实例化后的对象(实例化并且属性注入了),可以根据beanName来对特定的bean进行初始化前后的处理
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("lazyBean".equals(beanName)){
            System.out.println("MyBeanPostProcessor 拦截bean 初始化之前Before处理");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("lazyBean".equals(beanName)){
            System.out.println("MyBeanPostProcessor 拦截bean 初始化之后After处理");
        }
        return bean;
    }
}

我们来看下SpringBean的生命周期,如下图。
在这里插入图片描述
承接上面的代码,以LazyBean作为演示,实现BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean、BeanPostProcessor对应的方法,我们来打印下bean生命周期中的处理顺序:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class LazyBean implements BeanNameAware, BeanFactoryAware,
        ApplicationContextAware, InitializingBean, DisposableBean {
    public LazyBean() {
        System.out.println("lazyBean无参构造初始化------");
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("bean id是:" + s);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("创建bean的上层bean工厂是:" + beanFactory);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("高级容器接口ApplicationContext:" + applicationContext);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean 接口中afterPropertiesSet方法");
    }

    public void initMethod() {
        System.out.println("xml中init-method属性对应的初始化方法");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("注解@PostConstruct对应的初始方法");
    }

    //===================bean的销毁相关方法===================
    
    public void destroyMethod() {
        System.out.println("xml中destroy-method属性对应的销毁方法");
    }
    @PreDestroy
    public void preDestroy() {
        System.out.println("注解@PreDestroy对应的销毁方法");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean接口中的销毁方法");
    }
}
public class IocXmlTest {
    @Test
    public void TestIocContainer() {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Object lazyBean = applicationContext.getBean("lazyBean");
        System.out.println(lazyBean);
        System.out.println("===============销毁方法==============");
        applicationContext.close();
    }
}

控制台输出:

lazyBean无参构造初始化------
bean id是:lazyBean
创建bean的上层bean工厂是:org.springframework.beans.factory.support.DefaultListableBeanFactory@42eca56e: defining beans [myBeanPostProcessor,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,accountDao,transferService,connectionUtils,transactionManager,proxyFactory,lazyBean,companyBean]; root of factory hierarchy
高级容器接口ApplicationContext:org.springframework.context.support.ClassPathXmlApplicationContext@6d1e7682, started on Sun Aug 29 23:08:18 CST 2021
MyBeanPostProcessor 拦截bean 初始化之前Before处理
注解@PostConstruct对应的初始方法
InitializingBean 接口中afterPropertiesSet方法
xml中init-method属性对应的初始化方法
MyBeanPostProcessor 拦截bean 初始化之后After处理
com.nanmao.LazyBean@19d37183
===============销毁方法==============
注解@PreDestroy对应的销毁方法
DisposableBean接口中的销毁方法
xml中destroy-method属性对应的销毁方法

注意:注解@PostConstruct和注解@PreDestroy的执行过程要早于xml中init-method属性和destroy-method属性配置的对应的方法

(2) BeanFactoryPostProcessor

BeanFactory级别的处理,是针对整个Bean的工厂进行处理,典型应用:PropertyPlaceholderConfigurer。

@FunctionalInterface
public interface BeanFactoryPostProcessor {

	/**
	 * Modify the application context's internal bean factory after its standard
	 * initialization. All bean definitions will have been loaded, but no beans
	 * will have been instantiated yet. This allows for overriding or adding
	 * properties even to eager-initializing beans.
	 * @param beanFactory the bean factory used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

在这里插入图片描述
此接口只提供了?个方法,方法参数为ConfigurableListableBeanFactory。该参数类型定义了?些方法,其中有个方法名为getBeanDefinition的?法,我们可以根据此方法,找到我们定义bean 的BeanDefinition对象。然后我们可以对定义的属性进行修改,以下是BeanDefinition中的方法:

在这里插入图片描述
方法法名字类似我们bean标签的属性,setBeanClassName对应bean标签中的class属性,所以当我们拿到BeanDefinition对象时,我们可以手动修改bean标签中所定义的属性值。
BeanDefinition对象:我们在 XML 中定义的 bean标签,Spring 解析 bean 标签成为?个JavaBean,这个JavaBean 就是 BeanDefinition。
注意:调用BeanFactoryPostProcessor方法时,这时候bean还没有实例化,此时bean刚被解析成BeanDefinition对象。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章           查看所有文章
加:2021-09-02 11:13:10  更:2021-09-02 11:15:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:19:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码