Spring初探之BeanPostProcessor实现和手写BeanPostProcessor

本文深入探讨了Spring中的BeanPostProcessor接口,它允许在Bean实例化和初始化过程中插入自定义逻辑。首先介绍了BeanPostProcessor的工作原理,然后通过一个简单的例子展示了如何手写BeanPostProcessor,包括定义被监控行为、接口实现、通知类和监听对象。最后,文章演示了如何在自定义Spring容器中注册和使用BeanPostProcessor。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

BeanPostProcessor的主要作用在于我们可以在Spring 容器完成 Bean 的实例化、配置和其他的初始化前后添加一些自己的逻辑处理。我们就可以定义一个或者多个 BeanPostProcessor 接口的实现,然后注册到容器中。

BeanPostProcessor实现

其实这和代理模式的实现有些类似:
1、监控接口
定义所有需要被监听的行为
2、接口实现
谁来实现
3、通知类
次要业务具体实现 绑定主要和次要业务
4、监听对象
被监控的对象 需要被监控的行为 具体通知类实例对象 向JVM申请拦截
只不过是在Spring中,我们把代理对象交给Spring容器来实现了,按步骤来:
定义需要被监控的行为:
BaseService.java:

public interface BaseService {
    String doSomething();

    String eat();
}

谁来实现:
MyService.java

public class MyService implements BaseService{
    @Override
    public String doSomething() {
        return "doSomething";
    }

    @Override
    public String eat() {
        return "eat food";
    }
}

这里需要注意的是我们需要实现Spring的BeanPostProcessor接口:
MyBeanPostProcessor.java

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化之前。。。。postProcessBeforeInitialization");
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
        System.out.println("初始化后。。。。postProcessAfterInitialization");
        //只代理自定义的service
        if (bean.getClass() == MyService.class) {
            Proxy proxy = (Proxy) Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println(method + "方法被拦截。。。。invoke");
                    String result = (String) method.invoke(bean, args);
                    return result.toUpperCase();
                }
            });
            return proxy;
        }
        return bean;
    }
}

接着需要在Spring配置文件中配置相关属性:

<!-- 注册 bean:被监控的实现类 -->
    <bean id="myService" class="com.lks.processor.impl.MyService"></bean>

    <!-- 注册代理实现类 -->
    <bean class="com.lks.processor.proxy.MyBeanPostProcessor"></bean>

测试方法:

@Test
    public void testBeanPostProcessor() {
        ApplicationContext factory = new ClassPathXmlApplicationContext("spring_config.xml");
        BaseService service = (BaseService) factory.getBean("myService");
        System.out.println(service.doSomething());
    }
手写BeanPostProcessor

和Spring 一样,我们先需要定义BeanPostProcessor接口:

public interface BeanPostProcessor {

    default Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception {
        return bean;
    }

    default Object postProcessAfterInitializatio(Object bean, String beanName) throws Exception {
        return bean;
    }
}

接口实现方式基本和Spring的BeanPostProcessor接口一致,只不过这个是我们自己定义的。
接着我们需要在我们自定义的Spring容器,也就是BeanFactory中处理BeanPostProcessor:

public class BeanFactory {
    //存放bean集合
    private List<BeanDefined> beanDefinedList;

    //存放实例化对象
    private Map<String, Object> springIoc;

    //beanPostProcessor属性
    private BeanPostProcessor beanPostProcessor;
    public BeanFactory(){

    }
    public BeanFactory(List<BeanDefined> beanDefinedList) throws Exception {
        this.beanDefinedList = beanDefinedList;
        springIoc = new HashMap<>(16);
        for (BeanDefined bean: beanDefinedList){
            if ("singleton".equals(bean.getBeanScope())){
                String classPath = bean.getClassPath();
                Object instance = Class.forName(classPath).newInstance();
                //判断后置对象还是普通的bean
                isProcessor(instance, classPath);
                springIoc.put(bean.getBeanId(), instance);
            }
        }
    }
    private void isProcessor(Object instance, String classPath) {
        Class[] interfaces = instance.getClass().getInterfaces();
        if (interfaces == null){
            return;
        }
        for (Class c : interfaces){
            if (c == BeanPostProcessor.class){
                beanPostProcessor = (BeanPostProcessor) instance;
            }
        }
    }
    public Object getBeanPostProcessor(String beanId) throws Exception{
        Object instance = null;
        for (BeanDefined bean : beanDefinedList){
            if (beanId.equals(beanId)){
                if ("singleton".equals(bean.getBeanScope())){
                    instance = springIoc.get(beanId);
                }else {
                    if (bean.getFactoryBean() != null && bean.getFactoryMethod() != null){
                        Object factory = springIoc.get(bean.getFactoryBean());
                        Method method = factory.getClass().getDeclaredMethod(bean.getFactoryMethod(), null);
                        method.setAccessible(true);
                        instance = method.invoke(factory, null);
                    } else {
                        instance = Class.forName(bean.getClassPath()).newInstance();
                    }
                }
            }
            // 当前实例对象的代理监控对象
            Object proxyObj = null;
            //判断beanPostProcessor属性
            if (beanPostProcessor != null){
                proxyObj = beanPostProcessor.postProcessBeforeInitialization(instance, beanId);
                proxyObj = beanPostProcessor.postProcessAfterInitialization(instance, beanId);
                return proxyObj;
            }else {
                return instance;
            }
        }
        return null;
    }
}

新增BeanPostProcessor属性,在构造方法中判断当前的bean是不是BeanPostProcessor对象,如果是的话便初始化BeanPostProcessor,并在getBeanPostProcessor中判断返回代理对象还是普通的bean。
测试方法:

 @Test
    public void testMyBeanPostProcessor() throws Exception {
        //注册bean
        BeanDefined beanDefined = new BeanDefined();
        beanDefined.setBeanId("myService");
        beanDefined.setClassPath("com.lks.processor.impl.MyService");

        //注册BeanPostProcessor,类似Spring配置文件配置BeanPostProcessor
        BeanDefined beanObj1 = new BeanDefined();
        beanObj1.setClassPath("com.lks.processor.processor.MyBeanPostProcessor");
        List<BeanDefined> configuration = new ArrayList<BeanDefined>();
        configuration.add(beanDefined);
        configuration.add(beanObj1);
        // 2、声明一个BeanFactory,类似于Spring中的ApplicationContext
        BeanFactory factory = new BeanFactory(configuration);
        // 3、开发人员向BeanFactory索要实例对象
        BaseService b = (BaseService) factory.getBeanPostProcessor("myService");
        System.out.println("b =" + b);
        System.out.println("b方法 =" + b.doSomething());
    }

先注册bean,设置相关属性,然后类似Spring配置文件配置BeanPostProcessor中一样,设置BeanPostProcessor的位置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值