spring-两种后处理器

Posted zeromz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring-两种后处理器相关的知识,希望对你有一定的参考价值。

1、扩展IoC容器使用后处理器扩展

     bean后处理器:对容器中的bean进行后处理,也就是额外的加强。

     容器后处理:对IoC容器进行后处理,增强容器功能。

2、bean后处理器

     负责处理容器中的所有bean。

     bean后处理器必须实现BeanPostProcessor接口,提供非方法有:

          Object postProcessBeforeInitialization(Object bean,String name)throws BenasException:该方法第一个参数是系统即将进行后处理的bean实例,第二个参数是bean的配置id。在目标bean初始化之前被回调。

          Object postProcessAfterInitialization(Object bean,String name)throws BenasException:该方法第一个参数是系统即将进行后处理的bean实例,第二个参数是bean的配置id。在目标bean初始化之后被回调。

      举个例子:

      技术图片

      MyBeanPostProcessor.java

package com.lfy.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor 

    @Override
    public Object postProcessAfterInitialization(Object bean, String name) throws BeansException 
        
        System.out.println("bean后处理器在初始化之后对"+name+"进行增强处理...");
        return bean;
    

    @Override
    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException 
        
        System.out.println("bean后处理器在初始化之前对"+name+"进行增强处理...");
        return bean;
    

      Chinese.java

package com.lfy.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class Chinese implements InitializingBean,DisposableBean,BeanNameAware,ApplicationContextAware 
    
    private ApplicationContext ctx;
    private String beanID;
    private String someBodyName;

    public Chinese() 
        System.out.println("-----无参构造器-----");
    
    
    @Override
    public void setApplicationContext(ApplicationContext ctx) throws BeansException 
        this.ctx=ctx;
        System.out.println("-----获取ApplicationContext容器ctx-----");
    

    @Override
    public void setBeanName(String name) 
        this.beanID=name;
        System.out.println("-----获取bean id-----");
    
    
    /**
     * 生命周期方法afterPropertiesSet
     */
    @Override
    public void afterPropertiesSet() throws Exception 
        System.out.println("-----依赖关系注入之后,生命周期方法afterPropertiesSet-----");
    
    
    /**
     * 生命周期方法init
     */
    public void init() 
        System.out.println("-----依赖关系注入之后,生命周期方法init-----");
    

    /**
     * 生命周期方法destory
     */
    @Override
    public void destroy() throws Exception 
        System.out.println("-----bean销毁之前destroy-----");
    
    
    /**
     * 生命周期方法close
     */
    public void close() 
        System.out.println("-----bean销毁之前close-----");
    
    
    /**
     * setter方法
     * @param name
     */
    public void setSomeBodyName(String name) 
        this.someBodyName=name;
        System.out.println("-----property注入属性setter方法-----"+someBodyName);
    

      beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
      
      <bean id="chinese" class="com.lfy.bean.Chinese" init-method="init" destroy-method="close">
         <property name="someBodyName" value="至尊宝"/>
      </bean>
      
      <bean class="com.lfy.bean.MyBeanPostProcessor"/>
</beans>

      SpringTest.java

package com.lfy.main;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.lfy.bean.Chinese;

/**
 * 
 * @author lfy
 *
 */
public class SpringTest 

    public static void main(String[] args) 
        
        AbstractApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
        
        Chinese chin=ctx.getBean("chinese", Chinese.class);
        
        ctx.registerShutdownHook();
        System.exit(0);
    

      运行结果:

      技术图片

     总结:容器会自动将实现了BeanPostProcessor接口的bean注册为后处理器。它们之间执行的先后顺序如上。后处理会在每个bean创建时自动执行。

     使用BeanFactory作为spring容器,必须手动注册后处理器。

     bean后处理器的用处:

         1》BeanNameAutoProxyCreator:根据bean实例的name属性,创建bean实例的代理。

         2》DefaultAdvisorAutoProxyCreator:根据提供的Advisor,对容器中的所有bean实例创建代理。

3、容器后处理器

    负责处理容器本身。

    容器后处理器必须实现BeanFactoryPostProcessor接口,并实现postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory),在该方法中对spring容器进行自定义扩展。使用BeanFactory的容器需要手动注册后处理bean。

    举个例子:

    技术图片

    MyContainerPostProcessor.java

package com.lfy.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class MyContainerPostProcessor implements BeanFactoryPostProcessor 

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException 
        System.out.println("容器后处理器...spring容器是"+beanFactory);
    

     beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
      
      <!-- 遇到了个问题,destory-method="close"不能出现在<bean.../>,暂未明白原因  -->
      <bean id="chinese" class="com.lfy.bean.Chinese" init-method="init" destroy-method="close">
         <property name="someBodyName" value="至尊宝"/>
      </bean>
      
      <bean class="com.lfy.bean.MyBeanPostProcessor"/>
      <bean class="com.lfy.bean.MyContainerPostProcessor"/>
</beans>

     运行结果:

技术图片

    总结:如果有需要,可以配置多个容器后处理器,多个容器后处理器可设置order属性来控制容器后处理器的执行顺序,但需要容器后处理器实现Ordered接口。

以上是关于spring-两种后处理器的主要内容,如果未能解决你的问题,请参考以下文章

Spring的BeanPostProcessor和BeanFactoryPostProcessor区别

Spring针对事务处理提供哪两种事务编程模式。

Spring data JPA 理解(默认查询 自定义查询 分页查询)及no session 两种处理方法

Spring Boot中实现定时任务的两种方式

spring data jpa使用spring data jpa时,关于service层一个方法中进行删除和插入两种操作在同一个事务内处理

Spring Bean的后置处理