手写简易版Spring框架(七):定义标记类型接口Aware,实现感知容器相关的信息

文末有惊喜

目标

目前已实现的 Spring 框架,在 Bean 操作上能提供出的能力,包括:Bean 对象的定义和注册,以及在操作 Bean 对象过程中执行的,BeanFactoryPostProcessor、BeanPostProcessor、InitializingBean、DisposableBean,以及在 XML 新增的一些配置处理,让我们可以 Bean 对象有更强的操作性。

那么,如果我们想获得 Spring 框架提供的 BeanFactory、ApplicationContext、BeanClassLoader等这些能力做一些扩展框架的使用时该怎么操作呢。所以我们本章节希望在 Spring 框架中提供一种能感知容器操作的接口,如果谁实现了这样的一个接口,就可以获取接口入参中的各类能力。

设计

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

在关于 Bean 对象实例化阶段我们操作过一些额外定义、属性、初始化和销毁的操作,其实我们如果像获取 Spring 一些如 BeanFactory、ApplicationContext 时,也可以通过此类方式进行实现。那么我们需要定义一个标记性的接口,这个接口不需要有方法,它只起到标记作用就可以,而具体的功能由继承此接口的其他功能性接口定义具体方法,最终这个接口就可以通过 instanceof 进行判断和调用了。整体设计结构如下图:
在这里插入图片描述

  • 定义接口 Aware,在 Spring框架中它是一种感知标记性接口,具体的子类定义和实现能感知容器中的相关对象。也就是通过这个桥梁,向具体的实现类中提供容器服务
  • 继承 Aware 的接口包括:BeanFactoryAware、BeanClassLoaderAware、BeanNameAware和ApplicationContextAware,当然在Spring 源码中还有一些其他关于注解的,不过目前我们还是用不到。
  • 在具体的接口实现过程中你可以看到,一部分(BeanFactoryAware、BeanClassLoaderAware、BeanNameAware)在factory 的 support 文件夹下,另外 ApplicationContextAware 是在 context 的support 中,这是因为不同的内容获取需要在不同的包下提供。所以,在AbstractApplicationContext的具体实现中会用到向 beanFactory 添加 BeanPostProcessor 内容的ApplicationContextAwareProcessor 操作,最后由AbstractAutowireCapableBeanFactory 创建 createBean 时处理相应的调用操作。

类图:
在这里插入图片描述

  • 以上整个类关系就是关于 Aware 感知的定义和对容器感知的实现。
  • Aware 有四个继承的接口,其他这些接口的继承都是为了继承一个标记,有了标记的存在更方便类的操作和具体判断实现。
  • 另外由于 ApplicationContext 并不是在 AbstractAutowireCapableBeanFactory 中createBean 方法下的内容,所以需要像容器中注册 addBeanPostProcessor ,再由 createBean统一调用 applyBeanPostProcessorsBeforeInitialization 时进行操作。

实现

定义标记接口

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

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

容器感知类

BeanFactoryAware

public interface BeanFactoryAware extends Aware {
    
    

   void setBeanFactory(BeanFactory beanFactory) throws BeansException;

}

Interface to be implemented by beans that wish to be aware of their owning {@link BeanFactory}.
实现此接口,就能感知到所属的 BeanFactory

BeanClassLoaderAware

public interface BeanClassLoaderAware extends Aware{
    
    

    void setBeanClassLoader(ClassLoader classLoader);

}

Callback that allows a bean to be aware of the bean{@link ClassLoader class loader}; that is, the class loader used by the present bean factory to load bean classes.
实现此接口,就能感知到所属的 ClassLoader。

BeanNameAware

public interface BeanNameAware extends Aware {
    
    

    void setBeanName(String name);

}

Interface to be implemented by beans that want to be aware of their bean name in a bean factory.
实现此接口,就能感知到所属的 BeanName。

ApplicationContextAware

public interface ApplicationContextAware extends Aware {
    
    

    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}

Interface to be implemented by any object that wishes to be notifiedof the {@link ApplicationContext} that it runs in.
实现此接口,就能感知到所属的 ApplicationContext

包装处理器(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 方法调用。

注册 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。

感知调用操作

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;
    }

}

这里我们去掉了一些类的内容,只保留关于本次 Aware 感知接口的操作。

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

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

测试

事先准备

public class UserDao {
    
    
    private static Map<String, String> hashMap = new HashMap<>();

    public void initDataMethod(){
    
    
        System.out.println("执行:init-method");
        hashMap.put("10001", "青云先生");
        hashMap.put("10002", "張青云");
        hashMap.put("10003", "云鸽");
    }

    public void destroyDataMethod(){
    
    
        System.out.println("执行: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,四个感知的实现类,并在类中实现相应的接口方法。

XML配置文件:

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

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

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

</beans>

单元测试

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

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

结果

在这里插入图片描述
可以发现,我们获取到了Spring容器的一些相关信息!

项目代码Github地址:https://github.com/Zhang-Qing-Yun/mini-spring,本节代码对应的commit标识为610f169

欢迎标星


闲言碎语(与正文无关)

最近关注了一个公众号,分享一些内容给大家:

文艺型

1.“这个人也许永远不回来了,也许明天回来!”

——沈从文《边城》

2.“爸爸的花儿落了,我也不再是小孩子了。”

——林海音《城南旧事》

3.人类的全部智慧就包含在这两个词里面:等待和希望。

——大仲马《基督山伯爵》

4.一尘不染不是没有尘埃,而是尘埃任它飞扬,我自做我的阳光。

——林清玄

5.三号路依然长的没有尽头,梧桐荫还是枝繁叶茂,人间骄阳正好,风过林梢,彼时,他们正当年少。

——《某某》
6.世界灿烂盛大,欢迎回家。

——《全球高考》

7.一个时代的落幕,成是将再外是另一个时代的起点。

——《杀破狼》

8.想买束花给你,可路口的花店没开,我又实在想念。

——《穿堂惊掠琵琶声》

9.“…如果他不喝酒…不,就算喝了酒,他也是一个神一样的好孩子。”

——太宰治《人间失格》

10.生命是有光的。在我熄灭以前,能够照亮你一点,就是我所有能做的了。我爱你,你要记得我。

——《云边有个小卖部》

11.她一次都没有回头。

——《白夜行》

12.“只要岁岁平安,即使生生不见”

——《十年一品温如言》

13.以此书 纪念我的童年 那是一段小有遗憾的幸福时光。

——雷欧幻想

14.这个时间落伍的计时机无意中包涵对人生的讽刺和感伤,深于一切语言、一切啼笑。

——《围城》

15.“每个人一辈子皆会遇见两个人,最后,一个在心上,一个在远方”

——《香蜜沉沉烬如霜》

温柔型

1.温柔半两,从容一生。

2.我一生都在追逐自由 谁都别想以爱之名束缚我

3.从黎明到黄昏,阳光充足,胜过一切过去的诗。

——海子

4.一尘不染不是没有尘埃,而是尘埃任它飞扬,我自做我的阳光。

——林清玄

5.我想成为温柔的人,因为曾被温柔以待,深深了解那种温柔的感觉。

——村井贞之《夏目友人帐》

6.一朵花坠落的速度,连时间都放慢了脚步。

7.尽全力在不愉快的日子里搜刮生活藏下的所有温柔。

8.世间风物论自由,喜一生我有,共四海丰收。

——熊培云

9.我本是槐花院落闲散的人,满襟酒气,小池塘边跌坐看鱼,眉挑烟火过一生。

——沈离淮

10.繁花落尽,我心中仍有花落的声音。一朵,一朵,在无人的山间轻轻飘落。

——席慕容

11.爱自己是终生浪漫的开始。

——王尔德

12.可惜一溪风月,莫教踏碎琼瑶。

——苏轼

13.愿你的生命中有够多的云翳,来造成一个美丽的黄昏。

——冰心

14.这世间温柔,不过是芳春柳摇染花香,槐序蝉鸣入深巷。

15.关于沉溺与坠落的时刻,要记住,更要去相信,相信纯粹与正义,风的低语,相信所有行动皆有意义,铁会融化在雪里,而我们终会在岸边相遇。

——班宇

猜你喜欢

转载自blog.csdn.net/zhang_qing_yun/article/details/119851164