本文转载自微信公众号「bugstack虫洞栈」,作者小傅哥 。转载本文请联系bugstack虫洞栈公众号。
目前创新互联已为成百上千家的企业提供了网站建设、域名、虚拟空间、网站托管运营、企业网站设计、婺源网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
同事写的代码,我竟丝毫看不懂!
大佬的代码,就像“赖蛤蟆泡青蛙,张的丑玩的花”:一个类实现了多个接口、继承的类又继承了其他类、接口还可以和接口继承、实现接口的抽象类再由类实现抽象类方法、类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 进行判断和调用了。整体设计结构如下图:
- 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
Spring 感知接口的设计和实现类关系,如图 9-2
图 9-2
- /**
- * 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.1 BeanFactoryAware
- public interface BeanFactoryAware extends Aware {
- void setBeanFactory(BeanFactory beanFactory) throws BeansException;
- }
3.2 BeanClassLoaderAware
cn.bugstack.springframework.beans.factory.BeanClassLoaderAware
- public interface BeanClassLoaderAware extends Aware{
- void setBeanClassLoader(ClassLoader classLoader);
- }
3.3 BeanNameAware
cn.bugstack.springframework.beans.factory.BeanNameAware
- public interface BeanClassLoaderAware extends Aware{
- void setBeanClassLoader(ClassLoader classLoader);
- }
3.4 ApplicationContextAware
cn.bugstack.springframework.context.ApplicationContextAware
- public interface ApplicationContextAware extends Aware {
- void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
- }
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 方法调用。
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();
- }
- // ...
- }
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;
- }
- }
cn.bugstack.springframework.test.bean.UserDao
- public class UserDao {
- private static Map
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,四个感知的实现类,并在类中实现相应的接口方法。
基础配置,无BeanFactoryPostProcessor、BeanPostProcessor,实现类
本章节中并没有额外新增加配置信息,与上一章节内容相同。
- @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());
- }
测试结果
- 执行: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 对象的生命周期,已经有了很多的体现。整体总结如下图:
本章节关于 Aware 的感知接口的四个继承接口 BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware 的实现,又扩展了 Spring 的功能。如果你有做过关于 Spring 中间件的开发那么一定会大量用到这些类,现在你不只是用过,而且还知道他们都是什么时候触达的,在以后想排查类的实例化顺序也可以有一个清晰的思路了。
每一章节内容的实现都是在以设计模式为核心的结构上填充各项模块的功能,单纯的操作编写代码并不会有太多收获,一定是要理解为什么这么设计,这么设计的好处是什么,怎么就那么多接口和抽象类的应用,这些才是 Spring 框架学习的核心所在。
网站题目:虎行有雨,定义标记类型Aware接口,实现感知容器对象
网页地址:http://www.shufengxianlan.com/qtweb/news3/394403.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联