手写Spring8(Aware感知容器变化)

本文详细介绍了如何在Spring框架中实现BeanFactory、ApplicationContext等资源的感知,通过定义标记接口和实现特定的感知接口,如BeanFactoryAware、BeanNameAware等,使Bean能够获取到Spring容器的相关信息。同时,文章通过项目结构展示了BeanPostProcessor的使用,以及在测试中如何验证这些感知接口的生效。最后,文章总结了Spring中Bean生命周期的关键步骤。


目标

本章目标实现获得Spring 框架提供的 BeanFactory、ApplicationContext、BeanClassLoader、ApplicationContextAware等这些能力.,并且还知道他们都是什么时候触发的,在以后想排查类的实例化顺序也可以有一个清晰的思路了。

在 Spring 框架中提供一种能感知容器操作的接口,如果谁实现了这样的一个接口,就可以获取接口入参中的各类能力


设计思想

如果说我希望拿到 Spring 框架中一些提供的资源,那么首先需要考虑以一个什么方式去获取,之后你定义出来的获取方式,在 Spring 框架中该怎么去承接,实现了这两项内容,就可以扩展出你需要的一些属于 Spring 框架本身的能力了。

在关于 Bean 对象实例化阶段我们操作过一些额外定义、属性、初始化和销毁的操作,其实我们如果像获取 Spring 一些如 BeanFactory、ApplicationContext 时,也可以通过此类方式进行实现

那么我们需要定义一个标记性的接口,这个接口不需要有方法,它只起到标记作用就可以,而具体的功能由继承此接口的其他功能性接口定义具体方法,最终这个接口就可以通过 instanceof 进行判断和调用了。整体设计结构如下图
在这里插入图片描述


项目结构

在这里插入图片描述

在这里插入图片描述


一、实现

1、定义标记接口

/**
 * 标记类接口,实现该接口可以被Spring容器感知
 */
public interface Aware {

}

在 Spring 中有特别多类似这样的标记接口的设计方式,它们的存在就像是一种标签一样,可以方便统一摘取出属于此类接口的实现类,通常会有 instanceof 一起判断使用。


2、容器感知类

2.1、BeanFactoryAware

public interface BeanFactoryAware extends Aware {

   void setBeanFactory(BeanFactory beanFactory) throws BeansException;

}

实现此接口,就能感知到所属的 BeanFactory


2.2、BeanFactoryAware

public interface BeanFactoryAware extends Aware {

   void setBeanFactory(BeanFactory beanFactory) throws BeansException;

}


实现此接口,既能感知到所属的 ClassLoader


2.3、BeanNameAware

public interface BeanNameAware extends Aware{

    void setBeanName(String name);

}

实现此接口,既能感知到所属的 BeanName


2.4、ApplicationContextAware

public interface ApplicationContextAware extends Aware{

    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}

实现此接口,既能感知到所属的 ApplicationContext

3、包装处理器(ApplicationContextAwareProcessor)

public class ApplicationContextAwareProcessor implements BeanPostProcessor {

    private final ApplicationContext applicationContext;

    public ApplicationContextAwareProcessor(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware) bean).setApplicationContext(applicationContext);
        }
        return bean;
    }

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

由于 ApplicationContext 的获取并不能直接在创建 Bean 时候就可以拿到,所以需要在 refresh 操作时,把 ApplicationContext 写入到一个包装的 BeanPostProcessor 中去,再由 AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization 方法调用


4、注册 BeanPostProcessor

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {

    @Override
    public void refresh() throws BeansException {
        // 1. 创建 BeanFactory,并加载 BeanDefinition
        refreshBeanFactory();

        // 2. 获取 BeanFactory
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();

        // 3. 添加 ApplicationContextAwareProcessor,让继承自 ApplicationContextAware 的 Bean 对象都能感知所属的 ApplicationContext
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

        // 4. 在 Bean 实例化之前,执行 BeanFactoryPostProcessor (Invoke factory processors registered as beans in the context.)
        invokeBeanFactoryPostProcessors(beanFactory);

        // 5. BeanPostProcessor 需要提前于其他 Bean 对象实例化之前执行注册操作
        registerBeanPostProcessors(beanFactory);

        // 6. 提前实例化单例Bean对象
        beanFactory.preInstantiateSingletons();
    }
    
 	// ...   
}    

refresh() 方法就是整个 Spring 容器的操作过程,与上一章节对比,本次新增加了关于 addBeanPostProcessor 的操作。

添加 ApplicationContextAwareProcessor,让继承自 ApplicationContextAware 的 Bean 对象都能感知所属的 ApplicationContext。


5、感知调用操作

因为这个类代码太多,这里只展示展示本章相关类的代码,

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

    private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
        Object bean = null;
        try {
            bean = createBeanInstance(beanDefinition, beanName, args);
            // 给 Bean 填充属性
            applyPropertyValues(beanName, bean, beanDefinition);
            // 执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法
            bean = initializeBean(beanName, bean, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("Instantiation of bean failed", e);
        }

        // 注册实现了 DisposableBean 接口的 Bean 对象
        registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);

        addSingleton(beanName, bean);
        return bean;
    }

    private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) {

        // invokeAwareMethods
        if (bean instanceof Aware) {
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(this);
            }
            if (bean instanceof BeanClassLoaderAware){
                ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
            }
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
        }

        // 1. 执行 BeanPostProcessor Before 处理
        Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);

        // 执行 Bean 对象的初始化方法
        try {
            invokeInitMethods(beanName, wrappedBean, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e);
        }

        // 2. 执行 BeanPostProcessor After 处理
        wrappedBean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
        return wrappedBean;
    }



    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (null == current) return result;
            result = current;
        }
        return result;
    }

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (null == current) return result;
            result = current;
        }
        return result;
    }

}

public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements ConfigurableBeanFactory {

    /**
     * ClassLoader to resolve bean class names with, if necessary
     */
    private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();

    //...

    public ClassLoader getBeanClassLoader() {
        return this.beanClassLoader;
    }
}

1、在AbstractAutowireCapableBeanFactory 的initializeBean (初始化方法)中添加判断,通过判断 bean instanceof Aware,调用了三个接口方法,BeanFactoryAware.setBeanFactory(this)、BeanClassLoaderAware.setBeanClassLoader(getBeanClassLoader())、BeanNameAware.setBeanName(beanName),这样就能通知到已经实现了此接口的类。

2、在AbstractBeanFactory抽象类中添加beanClassLoader和提供get方法,

3、另外我们还向 BeanPostProcessor 中添加了 ApplicationContextAwareProcessor,此时在这个方法中也会被调用到具体的类实现,得到一个 ApplicationContex 属性


二、测试

1、事先准备

public class UserDao {

    private static Map<String, String> hashMap = new HashMap<>();

    public void initDataMethod(){
        System.out.println("UserDao xml的实现, 执行:init-method");
        hashMap.put("10001", "ljc");
        hashMap.put("10002", "yaya");
        hashMap.put("10003", "zz");
    }

    public void destroyDataMethod(){
        System.out.println("UserDao xml的实现, 执行:destroy-method");
        hashMap.clear();
    }

    public String queryUserName(String uId) {
        return hashMap.get(uId);
    }

}
public class UserService implements BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware {

    private ApplicationContext applicationContext;
    private BeanFactory beanFactory;

    private String uId;
    private String company;
    private String location;
    private UserDao userDao;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

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

    @Override
    public void setBeanName(String name) {
        System.out.println("Bean Name is:" + name);
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("ClassLoader:" + classLoader);
    }

    // ...get/set
}

UserDao 本次并没有什么改变,还是提供了关于初始化的方法,并在 Spring.xml 中提供 init-method、destroy-method 配置信息。

UserService 新增加,BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware,四个感知的实现类,并在类中实现相应的接口方法


2、配置文件

基础配置,无BeanFactoryPostProcessor、BeanPostProcessor,实现类

<?xml version="1.0" encoding="UTF-8"?>
<beans>

    <bean id="userDao" class="springframework.test.bean.UserDao" init-method="initDataMethod" destroy-method="destroyDataMethod"/>

    <bean id="userService" class="springframework.test.bean.UserService">
        <property name="uId" value="10001"/>
        <property name="company" value="腾讯"/>
        <property name="location" value="深圳"/>
        <property name="userDao" ref="userDao"/>
    </bean>

</beans>

本章节中并没有额外新增加配置信息,与上一章节内容相同。


3、单元测试

@Test
public void test_xml() {
    // 1.初始化 BeanFactory
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
    applicationContext.registerShutdownHook();      

    // 2. 获取Bean对象调用方法
    UserService userService = applicationContext.getBean("userService", UserService.class);
    String result = userService.queryUserInfo();
    System.out.println("测试结果:" + result);
    System.out.println("ApplicationContextAware:"+userService.getApplicationContext());
    System.out.println("BeanFactoryAware:"+userService.getBeanFactory());

测试方法中主要是添加了一写关于新增 Aware 实现的调用,其他不需要调用的也打印了相应的日志信息,可以在测试结果中看到。

UserDao xml的实现, 执行:init-method
ClassLoadersun.misc.Launcher$AppClassLoader@14dad5dc
Bean Name is:userService
测试结果:ljc, 公司:腾讯, 地点深圳
ApplicationContextAwarecn.ljc.springframework.context.support.ClassPathXmlApplicationContext@153f5a29
BeanFactoryAwarecn.ljc.springframework.beans.factory.support.DefaultListableBeanFactory@7f560810
UserDao xml的实现, 执行:destroy-method

Process finished with exit code 0

从测试结果可以看到,本章节新增加的感知接口对应的具体实现(BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware),已经可以如期输出结果了。


总结

目前关于 Spring 框架的实现中,某些功能点已经越来趋向于完整,尤其是 Bean 对象的生命周期,已经有了很多的体现,结构如下图

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

未闻花名丶丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值