Spring BeanPostProcessor 接口

2023-10-06 11:05

本文主要是介绍Spring BeanPostProcessor 接口,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Spring BeanPostProcessor 接口

目录

Spring BeanPostProcessor 接口

Spring bean定义继承


BeanPostProcessor 的接口定义,可以实现提供自己的实例化逻辑,依赖解析逻辑等,也可以以后在Spring容器实例化完毕,配置和初始化一个bean通过插入一个或多个的BeanPostProcessor实现一些自定义逻辑回调方法实现。

可以配置多个的BeanPostProcessor接口,控制这些的BeanPostProcessor接口,通过设置属性顺序执行顺序提供的BeanPostProcessor实现了Ordered接口。

BeanPostProcessor可以对bean(或对象)操作实例,这意味着Spring IoC容器实例化一个bean实例,然后BeanPostProcessor的接口做好自己的工作。

ApplicationContext会自动检测已定义实现的BeanPostProcessor接口和注册这些bean类为后置处理器,可然后通过在容器创建bean,在适当时候调用任何bean。

示例:

下面的示例显示如何编写,注册和使用BeanPostProcessor 可以在一个ApplicationContext 的上下文。

使用Eclipse IDE,然后按照下面的步骤来创建一个Spring应用程序:

步骤描述
1Create a project with a name SpringExample and create a package com.manongjc under the src folder in the created project.
2Add required Spring libraries using Add External JARs option as explained in the Spring Hello World Example chapter.
3Create Java classes HelloWorldInitHelloWorld and MainApp under the com.manongjcpackage.
4Create Beans configuration file Beans.xml under the src folder.
5The final step is to create the content of all the Java files and Bean Configuration file and run the application as explained below.

这里是 HelloWorld.java 文件的内容:

package com.manongjc;public class HelloWorld {private String message;public void setMessage(String message){this.message  = message;}public void getMessage(){System.out.println("Your Message : " + message);}public void init(){System.out.println("Bean is going through init.");}public void destroy(){System.out.println("Bean will destroy now.");}
}

这是实现BeanPostProcessor,之前和之后的任何bean的初始化它打印一个bean的名字非常简单的例子。可以因为有两个后处理器的方法对内部bean对象访问之前和实例化一个bean后执行更复杂的逻辑。

这里是InitHelloWorld.java文件的内容:

package com.manongjc;import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.BeansException;public class InitHelloWorld implements BeanPostProcessor {public Object postProcessBeforeInitialization(Object bean,String beanName) throws BeansException {System.out.println("BeforeInitialization : " + beanName);return bean;  // you can return any other object as well}public Object postProcessAfterInitialization(Object bean,String beanName) throws BeansException {System.out.println("AfterInitialization : " + beanName);return bean;  // you can return any other object as well}}

以下是MainApp.java 文件的内容。在这里,需要注册一个关闭挂钩registerShutdownHook() 是在AbstractApplicationContext类中声明的方法。这将确保正常关闭,并调用相关的destroy方法。

package com.manongjc;import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class MainApp {public static void main(String[] args) {AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");HelloWorld obj = (HelloWorld) context.getBean("helloWorld");obj.getMessage();context.registerShutdownHook();}
}

下面是init和destroy方法需要的配置文件beans.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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><bean id="helloWorld" class="com.manongjc.HelloWorld"init-method="init" destroy-method="destroy"><property name="message" value="Hello World!"/></bean><bean class="com.manongjc.InitHelloWorld" /></beans>

创建源代码和bean配置文件完成后,让我们运行应用程序。如果一切顺利,这将打印以下信息:

​BeforeInitialization : helloWorld
Bean is going through init.
AfterInitialization : helloWorld
Your Message : Hello World!
Bean will destroy now.​

Spring bean定义继承

一个bean定义包含了大量的配置信息,包含了构造器参数,属性值,和容器指定的信息,比如初始化方法,静态工厂方法名,等等。子bean从父bean那里继承配置数据。子定义可以重写一些值,或者按需添加别的值。使用子和父beans定义可以节约大量的输入。这就是使用模板的高效。

如果你使用ApplicationContext接口程序化编程,子bean定义由ChildBeanDefinition类表示。大多数使用者不会在这个级别使用它们,而是配置bean定义声明,比如ClassPathXmlApplicationContext。当你使用基于XML配置元数据时,你使用parent属性指定一个子bean定义,指定父bean作为这个属性的值。

<bean id="inheritedTestBean" abstract="true"class="org.springframework.beans.TestBean"><property name="name" value="parent"/><property name="age" value="1"/>
</bean><bean id="inheritsWithDifferentClass"class="org.springframework.beans.DerivedTestBean"parent="inheritedTestBean" init-method="initialize"><property name="name" value="override"/><!-- the age property value of 1 will be inherited from  parent --></bean>

一个子bean定义使用了来自父bean定义的bean类。如果没有指定,但也可以重写。在后面的案例中,子bean类必须与父bean类是兼容的,即,其必须接受父类的属性值。

一个子bean定义从其父bean中继承了构造器参数值,属性值,和方法重写,其还可以添加新的值。燃和初始化方法,销毁方法,并且/或者静态工厂方法设置将重写对应的父bean的设置。

剩下的设置总是从子定义中获取:depends on,autowire mode,依赖检查,singleton,scope,延迟加载。

前面的例子明确指定了父bean为abstract类型,其通过属性abstrat指定。如果父定义没有指定一个类,明确指定其为abstract是必须的。

<bean id="inheritedTestBeanWithoutClass" abstract="true"><property name="name" value="parent"/><property name="age" value="1"/>
</bean><bean id="inheritsWithClass" class="org.springframework.beans.DerivedTestBean"parent="inheritedTestBeanWithoutClass" init-method="initialize"><property name="name" value="override"/><!-- age will inherit the value of 1 from the parent bean definition-->
</bean>

父bean不能自己实例化,因为它完成不了,并且它也标识为abstract。当一个定义是abstract,其仅仅是一个纯净的模板bean定义,专门为子定义服务。使用这个abstract bean定义,通过作为另一个bean的ref属性关联它或者调用getBean()还有父bean的id关联它,将返回错误。相似地,容器内部的preInstantiateSingletons()方法忽视了bean定义(其如abstract定义一样)。

注意:ApplicationContext 默认的预处理实例化所有的singletons。因此这是很重要的(至少对于singleton beans),如果你想使用一个父bean作为一个模板,并且这个定义指定了一个类,你必须确保abstract属性值为true,否则应用上下文将真的会预处理实例化这个abstract bean。

这篇关于Spring BeanPostProcessor 接口的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/152890

相关文章

Springboot请求和响应相关注解及使用场景分析

《Springboot请求和响应相关注解及使用场景分析》本文介绍了SpringBoot中用于处理HTTP请求和构建HTTP响应的常用注解,包括@RequestMapping、@RequestParam... 目录1. 请求处理注解@RequestMapping@GetMapping, @PostMappin

SpringBoot整合AOP及使用案例实战

《SpringBoot整合AOP及使用案例实战》本文详细介绍了SpringAOP中的切入点表达式,重点讲解了execution表达式的语法和用法,通过案例实战,展示了AOP的基本使用、结合自定义注解以... 目录一、 引入依赖二、切入点表达式详解三、案例实战1. AOP基本使用2. AOP结合自定义注解3.

SpringBoot简单整合ElasticSearch实践

《SpringBoot简单整合ElasticSearch实践》Elasticsearch支持结构化和非结构化数据检索,通过索引创建和倒排索引文档,提高搜索效率,它基于Lucene封装,分为索引库、类型... 目录一:ElasticSearch支持对结构化和非结构化的数据进行检索二:ES的核心概念Index:

Spring配置扩展之JavaConfig的使用小结

《Spring配置扩展之JavaConfig的使用小结》JavaConfig是Spring框架中基于纯Java代码的配置方式,用于替代传统的XML配置,通过注解(如@Bean)定义Spring容器的组... 目录JavaConfig 的概念什么是JavaConfig?为什么使用 JavaConfig?Jav

Spring Boot Interceptor的原理、配置、顺序控制及与Filter的关键区别对比分析

《SpringBootInterceptor的原理、配置、顺序控制及与Filter的关键区别对比分析》本文主要介绍了SpringBoot中的拦截器(Interceptor)及其与过滤器(Filt... 目录前言一、核心功能二、拦截器的实现2.1 定义自定义拦截器2.2 注册拦截器三、多拦截器的执行顺序四、过

springboot的controller中如何获取applicatim.yml的配置值

《springboot的controller中如何获取applicatim.yml的配置值》本文介绍了在SpringBoot的Controller中获取application.yml配置值的四种方式,... 目录1. 使用@Value注解(最常用)application.yml 配置Controller 中

springboot中配置logback-spring.xml的方法

《springboot中配置logback-spring.xml的方法》文章介绍了如何在SpringBoot项目中配置logback-spring.xml文件来进行日志管理,包括如何定义日志输出方式、... 目录一、在src/main/resources目录下,也就是在classpath路径下创建logba

SpringBoot返回文件让前端下载的几种方式

《SpringBoot返回文件让前端下载的几种方式》文章介绍了开发中文件下载的两种常见解决方案,并详细描述了通过后端进行下载的原理和步骤,包括一次性读取到内存和分块写入响应输出流两种方法,此外,还提供... 目录01 背景02 一次性读取到内存,通过响应输出流输出到前端02 将文件流通过循环写入到响应输出流

SpringBoot实现图形验证码的示例代码

《SpringBoot实现图形验证码的示例代码》验证码的实现方式有很多,可以由前端实现,也可以由后端进行实现,也有很多的插件和工具包可以使用,在这里,我们使用Hutool提供的小工具实现,本文介绍Sp... 目录项目创建前端代码实现约定前后端交互接口需求分析接口定义Hutool工具实现服务器端代码引入依赖获

SpringBoot项目整合Netty启动失败的常见错误总结

《SpringBoot项目整合Netty启动失败的常见错误总结》本文总结了SpringBoot集成Netty时常见的8类问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录一、端口冲突问题1. Tomcat与Netty端口冲突二、主线程被阻塞问题1. Netty启动阻