乐趣区

关于java:手写Spring定义标记类型Aware接口实现感知容器对象

作者:小傅哥
博客:https://bugstack.cn

积淀、分享、成长,让本人和别人都能有所播种!😄

一、前言

共事写的代码,我竟丝毫看不懂!

大佬的代码,就像 “赖蛤蟆泡青蛙,张的丑玩的花”:一个类实现了多个接口、继承的类又继承了其余类、接口还能够和接口继承、实现接口的抽象类再由类实现抽象类办法、类 A 继承的类 B 实现了类 A 实现的接口 C,等等。

看上去 简单又难懂 的代码,却又能一次次满足需要的高效迭代和顺利扩大,而像螺丝钉一样搬砖的你,只是在 大佬 写的代码里,实现某个接口下的一小块性能,甚至写完了也不晓得怎么就被调用运行了,整个过程像看 Spring 源码一样神奇,跳来跳去的摸不着脉络!

其实这次要是因为你的代码是否使用了设计模式,当然设计模式也没那么神奇,就像你们两家都是 120 平米的房子,他家有三室两厅一厨一卫,南北通透,全阳采光。但你家就不一样了,你家是锅碗瓢盆、卫浴马桶、沙发茶几还有那 1.8 的双人床,在 120 平米的房子里敞开了放,没有动静隔离,也没有干湿拆散,纯自由发挥。所以你的代码看上去就乱的很!

二、指标

目前已实现的 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 时解决相应的调用操作。对于 applyBeanPostProcessorsBeforeInitialization 曾经在后面章节中实现过,如果遗记能够往前翻翻

四、实现

1. 工程构造

small-spring-step-08
└── src
    ├── main
    │   └── java
    │       └── cn.bugstack.springframework
    │           ├── beans
    │           │   ├── factory
    │           │   │   ├── factory
    │           │   │   │   ├── AutowireCapableBeanFactory.java
    │           │   │   │   ├── BeanDefinition.java
    │           │   │   │   ├── BeanFactoryPostProcessor.java
    │           │   │   │   ├── BeanPostProcessor.java
    │           │   │   │   ├── BeanReference.java
    │           │   │   │   ├── ConfigurableBeanFactory.java
    │           │   │   │   └── SingletonBeanRegistry.java
    │           │   │   ├── support
    │           │   │   │   ├── AbstractAutowireCapableBeanFactory.java
    │           │   │   │   ├── AbstractBeanDefinitionReader.java
    │           │   │   │   ├── AbstractBeanFactory.java
    │           │   │   │   ├── BeanDefinitionReader.java
    │           │   │   │   ├── BeanDefinitionRegistry.java
    │           │   │   │   ├── CglibSubclassingInstantiationStrategy.java
    │           │   │   │   ├── DefaultListableBeanFactory.java
    │           │   │   │   ├── DefaultSingletonBeanRegistry.java
    │           │   │   │   ├── DisposableBeanAdapter.java
    │           │   │   │   ├── InstantiationStrategy.java
    │           │   │   │   └── SimpleInstantiationStrategy.java  
    │           │   │   ├── support
    │           │   │   │   └── XmlBeanDefinitionReader.java
    │           │   │   ├── Aware.java
    │           │   │   ├── BeanClassLoaderAware.java
    │           │   │   ├── BeanFactory.java
    │           │   │   ├── BeanFactoryAware.java
    │           │   │   ├── BeanNameAware.java
    │           │   │   ├── ConfigurableListableBeanFactory.java
    │           │   │   ├── DisposableBean.java
    │           │   │   ├── HierarchicalBeanFactory.java
    │           │   │   ├── InitializingBean.java
    │           │   │   └── ListableBeanFactory.java
    │           │   ├── BeansException.java
    │           │   ├── PropertyValue.java
    │           │   └── PropertyValues.java 
    │           ├── context
    │           │   ├── support
    │           │   │   ├── AbstractApplicationContext.java 
    │           │   │   ├── AbstractRefreshableApplicationContext.java 
    │           │   │   ├── AbstractXmlApplicationContext.java 
    │           │   │   ├── ApplicationContextAwareProcessor.java 
    │           │   │   └── ClassPathXmlApplicationContext.java 
    │           │   ├── ApplicationContext.java 
    │           │   ├── ApplicationContextAware.java 
    │           │   └── ConfigurableApplicationContext.java
    │           ├── core.io
    │           │   ├── ClassPathResource.java 
    │           │   ├── DefaultResourceLoader.java 
    │           │   ├── FileSystemResource.java 
    │           │   ├── Resource.java 
    │           │   ├── ResourceLoader.java 
    │           │   └── UrlResource.java
    │           └── utils
    │               └── ClassUtils.java
    └── test
        └── java
            └── cn.bugstack.springframework.test
                ├── bean
                │   ├── UserDao.java
                │   └── UserService.java
                └── ApiTest.java

工程源码 公众号「bugstack 虫洞栈」,回复:Spring 专栏,获取残缺源码

Spring 感知接口的设计和实现类关系,如图 9-2

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

2. 定义标记接口

cn.bugstack.springframework.beans.factory.Aware

/**
 * Marker superinterface indicating that a bean is eligible to be
 * notified by the Spring container of a particular framework object
 * through a callback-style method.  Actual method signature is
 * determined by individual subinterfaces, but should typically
 * consist of just one void-returning method that accepts a single
 * argument.
 *
 * 标记类接口,实现该接口能够被 Spring 容器感知
 *
 */
public interface Aware {}
  • 在 Spring 中有特地多相似这样的标记接口的设计形式,它们的存在就像是一种标签一样,能够不便对立摘取出属于此类接口的实现类,通常会有 instanceof 一起判断应用。

3. 容器感知类

3.1 BeanFactoryAware

cn.bugstack.springframework.beans.factory.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

3.2 BeanClassLoaderAware

cn.bugstack.springframework.beans.factory.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

3.3 BeanNameAware

cn.bugstack.springframework.beans.factory.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

3.4 ApplicationContextAware

cn.bugstack.springframework.context.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

4. 包装处理器(ApplicationContextAwareProcessor)

cn.bugstack.springframework.context.support.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 办法调用。

5. 注册 BeanPostProcessor

cn.bugstack.springframework.context.support.AbstractApplicationContext

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。

6. 感知调用操作

cn.bugstack.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

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 属性。

五、测试

1. 当时筹备

cn.bugstack.springframework.test.bean.UserDao

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

}

cn.bugstack.springframework.test.bean.UserService

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="cn.bugstack.springframework.test.bean.UserDao" init-method="initDataMethod" destroy-method="destroyDataMethod"/>

    <bean id="userService" class="cn.bugstack.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 实现的调用,其余不须要调用的也打印了相应的日志信息,能够在测试后果中看到。

测试后果

执行:init-method
ClassLoader:sun.misc.Launcher$AppClassLoader@14dad5dc
Bean Name is:userService
测试后果:小傅哥, 腾讯, 深圳
ApplicationContextAware:cn.bugstack.springframework.context.support.ClassPathXmlApplicationContext@5ba23b66
BeanFactoryAware:cn.bugstack.springframework.beans.factory.support.DefaultListableBeanFactory@2ff4f00f
执行:destroy-method



Process finished with exit code 0
  • 从测试后果能够看到,本章节新减少的感知接口对应的具体实现(BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware),曾经能够如期输入后果了。

六、总结

  • 目前对于 Spring 框架的实现中,某些性能点曾经越来趋向于残缺,尤其是 Bean 对象的生命周期,曾经有了很多的体现。整体总结如图 9-3

  • 本章节对于 Aware 的感知接口的四个继承接口 BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware 的实现,又扩大了 Spring 的性能。如果你有做过对于 Spring 中间件的开发那么肯定会大量用到这些类,当初你不只是用过,而且还晓得他们都是什么时候触达的,在当前想排查类的实例化程序也能够有一个清晰的思路了。
  • 每一章节内容的实现都是在以设计模式为外围的构造上填充各项模块的性能,单纯的操作编写代码并不会有太多播种,肯定是要了解为什么这么设计,这么设计的益处是什么,怎么就那么多接口和抽象类的利用,这些才是 Spring 框架学习的外围所在。

七、系列举荐

  • 大学毕业要写多少行代码,能力不必花钱培训就找到一份开发工作?
  • 90% 的程序员,都没用过多线程和锁,怎么成为架构师?
  • 握草,你居然在代码里下毒!
  • Netty+JavaFx 实战:仿桌面版微信聊天
  • 刚火了的中台转头就拆,一大波公司放不下又拿不起来!
退出移动版