Spring专区-定义自己的Aware接口

核心类介绍

BeanPostProcessor

该类是在Bean对象已经调用构造函数构造出对象后会使用该接口对应的实现类对象进行处
理,该接口包含两个方法:

Object postProcessBeforeInitialization(Object bean, String beanName) throws 
BeansException;

这个方法会在调用bean的init方法(比如bean继承了InitializingBean接口的afterPropertiesSet方法或者指定了init-method)之前进行调用,可以对bean进行一些操作,BeanAware相关的操作一般在这个方法内进行调用。

Object postProcessAfterInitialization(@NonNull Object bean, String beanName) 
throws BeansException;

这个方法会在调用bean的init方法之后进行调用,默认操作是直接返回bean,即不进行任何处理。

何时需要自己定义Aware接口?

最近我在实现分布式会话的过程中,遇到一个比较诡异的问题"No servlet context set",通过不断的打断点,找到的原因如下:我在代码配置Tomcat的SessionManager时,由于我的Manager注入了一些自定义的component,在正常情况下,Spring bean都是在Tomcat容器初始化之后才进行扫描注册。但是由于我定义的Manager引用了相关bean,导致Spring容器提前扫描了Configuration中的bean。而WebMvcConfigurationSupport作为一个Configuration,同样对其进行扫描并注册相关bean,由于其实现了ServletContextAware接口,但是由于Tomcat容器初始化未完成,WebMvcConfigurationSupport中的servletContext为null,所以定义某些依赖servletContext的bean时,由于Spring在前面进行了Assert.notNull断言,导致抛出"No servlet context set"的异常。

所以为了解决这些问题,我自定义了AwareProcessor延迟bean的注入,下面根据我的需要抽象了一个AbstractGenericAwareProcessor

/**
 * @author lidelin
 */
public abstract class AbstractGenericAwareProcessor<A> implements BeanPostProcessor, ApplicationContextAware {

    protected ApplicationContext applicationContext;

    @Override
    public Object postProcessBeforeInitialization(@NonNull Object bean, String beanName) throws BeansException {
        if (filterBean(beanName, bean)) {
            applicationContext.getBeansOfType(getAwareClass())
                    .forEach((k, v) -> {
                        processBean(beanName, bean, getAwareClass().cast(v));
                    });
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(@NonNull Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public void setApplicationContext(@NonNull ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    /**
     * 筛选bean
     * @param beanName bean name
     * @param bean bean
     * @return 是否符合
     */
    protected abstract boolean filterBean(String beanName, Object bean);

    /**
     * 获取需要处理的aware接口的类型
     * @return 类型
     */
    protected abstract Class<A> getAwareClass();

    /**
     * 处理符合条件的bean
     * @param beanName bean name
     * @param bean bean
     */
    protected abstract void processBean(String beanName, Object bean, A aware);
}

下面是一个注入RedisTemplate的实现样例:

/**
 * @author lidelin
 */
public class RedisTemplateAwareProcessor extends AbstractGenericAwareProcessor<RedisTemplateAware> {
    @Override
    protected boolean filterBean(String beanName, Object bean) {
        return bean instanceof RedisTemplate && "redisTemplate".equals(beanName);
    }

    @Override
    protected Class<RedisTemplateAware> getAwareClass() {
        return RedisTemplateAware.class;
    }

    @Override
    @SuppressWarnings("rawtypes")
    protected void processBean(String beanName, Object bean, RedisTemplateAware aware) {
        aware.setRedisTemplate((RedisTemplate) bean);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木子的木木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值