• 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 文件的内容:

    1. package com.manongjc;
    2. public class HelloWorld {
    3. private String message;
    4. public void setMessage(String message){
    5. this.message = message;
    6. }
    7. public void getMessage(){
    8. System.out.println("Your Message : " + message);
    9. }
    10. public void init(){
    11. System.out.println("Bean is going through init.");
    12. }
    13. public void destroy(){
    14. System.out.println("Bean will destroy now.");
    15. }
    16. }

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

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

    1. package com.manongjc;
    2. import org.springframework.beans.factory.config.BeanPostProcessor;
    3. import org.springframework.beans.BeansException;
    4. public class InitHelloWorld implements BeanPostProcessor {
    5. public Object postProcessBeforeInitialization(Object bean,
    6. String beanName) throws BeansException {
    7. System.out.println("BeforeInitialization : " + beanName);
    8. return bean; // you can return any other object as well
    9. }
    10. public Object postProcessAfterInitialization(Object bean,
    11. String beanName) throws BeansException {
    12. System.out.println("AfterInitialization : " + beanName);
    13. return bean; // you can return any other object as well
    14. }
    15. }

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

    1. package com.manongjc;
    2. import org.springframework.context.support.AbstractApplicationContext;
    3. import org.springframework.context.support.ClassPathXmlApplicationContext;
    4. public class MainApp {
    5. public static void main(String[] args) {
    6. AbstractApplicationContext context =
    7. new ClassPathXmlApplicationContext("Beans.xml");
    8. HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
    9. obj.getMessage();
    10. context.registerShutdownHook();
    11. }
    12. }

    下面是init和destroy方法需要的配置文件beans.xml文件:

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans
    5. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    6. <bean id="helloWorld" class="com.manongjc.HelloWorld"
    7. init-method="init" destroy-method="destroy">
    8. <property name="message" value="Hello World!"/>
    9. </bean>
    10. <bean class="com.manongjc.InitHelloWorld" />
    11. </beans>

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

    1. ​BeforeInitialization : helloWorld
    2. Bean is going through init.
    3. AfterInitialization : helloWorld
    4. Your Message : Hello World!
    5. Bean will destroy now.​

    Spring bean定义继承

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

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

    1. <bean id="inheritedTestBean" abstract="true"
    2. class="org.springframework.beans.TestBean">
    3. <property name="name" value="parent"/>
    4. <property name="age" value="1"/>
    5. </bean>
    6. <bean id="inheritsWithDifferentClass"
    7. class="org.springframework.beans.DerivedTestBean"
    8. parent="inheritedTestBean" init-method="initialize">
    9. <property name="name" value="override"/>
    10. <!-- the age property value of 1 will be inherited from parent -->
    11. </bean>

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

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

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

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

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

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

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

  • 相关阅读:
    java面向对象(六)
    结构型模式
    word如何设置页码?教你快速提升文档颜值!
    Go语言之channel实现原理
    css_背景属性所踩的坑
    AI+软件工程:10倍提效!用ChatGPT编写系统功能文档
    一本通1080;余数相同问题
    python学习03垃圾回收机制
    JavaScript中常见问题及解决
    『docker笔记』Centos7离线安装docker[补充CentOS开机自动启动脚本]
  • 原文地址:https://blog.csdn.net/2301_78835635/article/details/133604319