【HBZ分享】FactoryBean的应用 与 BeanFactroyPostProcessor的应用 与 BeanPostProcesser的应用

FactoryBean的应用实战

  1. 需要写一个A类来实现FactoryBean
  2. 实现FactoryBean的3个方法,即getOject(), getObjectType(), isSingleton()
  3. 注意:在通过xml的【 】标签或者通过注解方式将A类注入容器的时候,返回的实例不是A类,而是T类,因为他会自动的执行getObject()方法,而getObject()方法中new的是T类的对象,所以这块不要搞错了
  4. 下面代码案例: 有xml配置可见,bean注入的是MyFactoryBean, 但图中可以看出实例出来的却是ObjectBean类型的,

implements FactoryBean代码:

package com.spring.factoryBean实战;
import org.springframework.beans.factory.FactoryBean;
public class myFactoryBean implements FactoryBean<ObjectBean> {
    @Override
    public ObjectBean getObject() throws Exception {
        return new ObjectBean("hbz", 26);
    }
    @Override
    public Class<?> getObjectType() {
        return null;
	}
}

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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id = "myFactoryBean"  class="com.spring.factoryBean实战.myFactoryBean"></bean>
</beans>

在这里插入图片描述

BeanFactroyPostProcessor的应用实战

  1. BeanFactroyPostProcessor 会在 BeanPostProcessor之前执行, 即先执行BeanFactroyPostProcessor
  2. 作用:读取应用程序上下文,并对其属性进行修改, 可以修改BeanDefinition中的属性,比如设置单例多例(setScope), 是否是懒加载(setLazyInit()), 动态设置初始化方法等
  3. 执行BeanFactroyPostProcessor时还没有进行指定类的初始化(还未执行构造函数),所以通过BeanFactroyPostProcessor可以改变目标类属性
  4. 代码实战:
    FactoryBeanPostPorcess代码:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class MyBeanFacotryPostProcess implements BeanFactoryPostProcessor {

    public MyBeanFacotryPostProcess() {
        System.out.println("构造函数执行--------------------------");
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

        // 获取所有的bean
        String[] beanDefinitionNames = configurableListableBeanFactory.getBeanDefinitionNames();
        for(String befinitonName : beanDefinitionNames){
            if("productService".equalsIgnoreCase(befinitonName)){
                BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition(befinitonName);
                // 单例多例
                beanDefinition.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE);
                // 设置初始化方法
                beanDefinition.setInitMethodName("testInit");
            }
        }
    }
}

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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id = "productService"  class="com.spring.beanFactoryPostProcess实战.ProductServiceImpl" scope="singleton"></bean>

<!-- 这句需要加,表示启动的时候就注入到spring容器并运行一次, 这个类中就是设置ProductServiceImpl的属性的, 如果不写,那么动态配置的类属性是不会生效的-->
    <bean id = "myBeanFacotryPostProcess"  class="com.spring.beanFactoryPostProcess实战.MyBeanFacotryPostProcess"></bean>
</beans>

目标类代码:

package com.spring.beanFactoryPostProcess实战;

public class ProductServiceImpl implements ProductService{

    public ProductServiceImpl(){
        System.out.println("这个是构造函数");
    }

    @Override
    public void example() {
        System.out.println("类名: "+ this.getClass().toString());
    }


    public void testInit(){
        System.out.println("这个是初始化方法");
    }
}

输出结果:
在这里插入图片描述

BeanPostProcessor的应用

  1. BeanPostProcessor在BeanFactoryPostProcessor之后执行
  2. BeanPostProcessor作用于bean实例化过程中, 可以改变bean实例中的属性值, 比如bean中有个name = “123”, 则可以在BeanPostProcessor的两个实现方法中将其改成setName(“456”)
  3. BeanPostProcessor通常需要实现两个方法,分别是postProcessBeforeInitialization, postProcessAfterInitialization
  4. postProcessBeforeInitialization: 在目标类的【初始化方法】之前执行。postProcessAfterInitialization:在目标类【初始化方法之后】执行
  5. postProcessBeforeInitialization,postProcessAfterInitialization都会有个参数,叫【String beanName】, 这个beanName是容器中所有的bean(即容器有多少个bean,这俩方法就走多少遍),如果想在指定目标类触发BeanPostProcessor,则需要加一个判断。如果在xml定义了bean,则使用xml中定义的name去和beanName作比较,如果不是在xml中定义的,是new出来的,直接用目标类的【类名(首字母小写)】去和beanName比较,默认new出来的beanName就等于类名首字母小写
  6. 代码:

BeanPostProcessor实现类:

package com.spring.beanPostProcessor实战;

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

public class MyBeanPostProcessor implements BeanPostProcessor {

    /**
     * 在每个bean初始化方法之前执行
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

        System.out.println("MyBeanPostProcessor # BeforeInitialization 调用 beanName = " + beanName);
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    /**
     * 在每个bean初始化方法之后执行
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        System.out.println("MyBeanPostProcessor # AfterInitialization 调用 beanName = " + beanName);
        
        // 判断beanName,如果beanName = productBeanService, 则就执行如下操作
        if("productBeanService".equalsIgnoreCase(beanName)){
            ProductBeanServiceImpl productBeanService = (ProductBeanServiceImpl) bean;
            productBeanService.setName("v2.修改后的值");
            BeanPostProcessor.super.postProcessAfterInitialization(productBeanService, beanName);
        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id = "productBeanService"  class="com.spring.beanPostProcessor实战.ProductBeanServiceImpl" scope="singleton" init-method="testInit"></bean>

    <bean id = "myBeanPostProcessor"  class="com.spring.beanPostProcessor实战.MyBeanPostProcessor"></bean>
</beans>

目标类代码:

package com.spring.beanPostProcessor实战;

import org.springframework.beans.factory.InitializingBean;


/**
 * 实现InitializingBean就可以实现初始化方法,因为InitializingBean中的afterPropertiesSet就是初始化方法,无需通过xml指定
 */
public class ProductBeanServiceImpl implements ProductBeanService, InitializingBean {

    private String name = "v1.修改之前的值";

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ProductBeanServiceImpl(){
        System.out.println("这个是构造函数");
    }

    @Override
    public void example() {
        System.out.println("类名: "+ this.getClass().toString());
    }

    /**
     * BeanPostProcessor中的postProcessBeforeInitialization方法会在该初始化方法之前执行
     * BeanPostProcessor中的postProcessAfterInitialization方法会在该初始化方法之后执行
     *
     */
    public void testInit(){
        System.out.println("这是在xml或者BeanFactoryPostProcess中指定的初始化方法");
    }

    /**
     * 这个也是初始化方法,但必须实现InitializingBean
     * 效果: 和testInit()一摸一样,该方法不需要在xml中配置,而testInit需要在xml或者通过BeanFactoryPostProcess配置并指定testInit初始化方法才可以
     *
     *
     * BeanPostProcessor中的postProcessBeforeInitialization方法会在该初始化方法之前执行
     * BeanPostProcessor中的postProcessAfterInitialization方法会在该初始化方法之后执行
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("这是InitializingBean的初始化方法");
    }
}

启动类代码:

package com.spring.beanPostProcessor实战;

import com.spring.beanFactoryPostProcess实战.ProductServiceImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    public static void main(String[] args) {

        // 读取指定的配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath*:beanPostPorcessor.xml");
        ProductBeanServiceImpl productBeanService = (ProductBeanServiceImpl) context.getBean("productBeanService");
        System.out.println(productBeanService);
    }
}

执行结果截图:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值