做者:小傅哥
博客:https://bugstack.cnhtml
沉淀、分享、成长,让本身和他人都能有所收获!😄
你这代码,可不能写死了呀!
java
依照项目落地经验来看,咱们在承接紧急的产品需求时候,一般会选择在原有同类项目中进行扩展,若是没有相关类型项目的储备,也可能会选择临时搭建出一个工程来实现产品的需求。但这个时候就会遇到很是现实的问题,选择完整的设计和开发就可能知足不了上线时间,临时拼凑式的完成需求又可能不具有上线后响应产品的临时调整。面试
上线后的调整有哪些呢?项目刚一上线,运营了还不到半天,老板发现本身的配置的活动好像金额配置的过小了,用户都不来,割不到韭菜呀。赶忙半夜联系产品,来来来,你给我这改改,那修修,把人均优惠1万元放大大的,把可能两字缩小放在后面。再把优惠的奖金池配置从10元调整11元,快快快,赶忙修改,你修改了我们能赚1个亿!!!
spring
好家伙,项目是临时开发堆出来的,没有后台系统、没有配置中心、没有模块拆分,老板一句句改改改,产品来传达催促,最后背锅的可就是研发了。你这不能写死,这优惠配置得抽出来,这文案也后台下发吧,这接口入参也写死了,再写一个新接口吧! 一顿操做猛如虎,研发搬砖修接口,运营折腾好几宿,最后PV150!数据库
不管业务、产品、运营如何,但就研发自身来说,尽量的要不避免临时堆出一个服务来,尤为是在团队建设初期或者运营思路常常调整的状况下,更要注重设计细节和实现方案。哪怕去报风险延期,也不要让本身背上一个明知是烂坑还要接的活。设计模式
而本章节说到不把代码写死
,就是由于咱们须要继续在手写 Spring 框架中继续扩展新的功能,如一个Bean的定义和实例化的过程先后,是否能够知足咱们进行自定义扩展,对Bean对象执行一些修改、加强、记录等操做呢? 这个过程基本就是你在使用 Spring 容器框架时候作的一些中间件扩展开发。架构
若是你在本身的实际工做中开发过基于 Spring 的技术组件,或者学习过关于 SpringBoot 中间件设计和开发 等内容。那么你必定会继承或者实现了 Spring 对外暴露的类或接口,在接口的实现中获取了 BeanFactory 以及 Bean 对象的获取等内容,并对这些内容作一些操做,例如:修改 Bean 的信息,添加日志打印、处理数据库路由对数据源的切换、给 RPC 服务链接注册中心等。app
在对容器中 Bean 的实例化过程添加扩展机制的同时,还须要把目前关于 Spring.xml 初始化和加载策略进行优化,由于咱们不太可能让面向 Spring 自己开发的 DefaultListableBeanFactory
服务,直接给予用户使用。修改点以下:框架
为了能知足于在 Bean 对象从注册到实例化的过程当中执行用户的自定义操做,就须要在 Bean 的定义和初始化过程当中插入接口类,这个接口再有外部去实现本身须要的服务。那么在结合对 Spring 框架上下文的处理能力,就能够知足咱们的目标需求了。总体设计结构以下图:ide
BeanFactoryPostProcess
和 BeanPostProcessor
,也几乎是你们在使用 Spring 框架额外新增开发本身组建需求的两个必备接口。BeanDefinition
执行修改操做。small-spring-step-06 └── 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 │ │ │ │ ├── InstantiationStrategy.java │ │ │ │ └── SimpleInstantiationStrategy.java │ │ │ ├── support │ │ │ │ └── XmlBeanDefinitionReader.java │ │ │ ├── BeanFactory.java │ │ │ ├── ConfigurableListableBeanFactory.java │ │ │ ├── HierarchicalBeanFactory.java │ │ │ └── ListableBeanFactory.java │ │ ├── BeansException.java │ │ ├── PropertyValue.java │ │ └── PropertyValues.java │ ├── context │ │ ├── support │ │ │ ├── AbstractApplicationContext.java │ │ │ ├── AbstractRefreshableApplicationContext.java │ │ │ ├── AbstractXmlApplicationContext.java │ │ │ └── ClassPathXmlApplicationContext.java │ │ ├── ApplicationContext.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 ├── common │ ├── MyBeanFactoryPostProcessor.java │ └── MyBeanPostProcessor.java └── ApiTest.java
工程源码:公众号「bugstack虫洞栈」,回复:Spring 专栏,获取完整源码
Spring 应用上下文和对Bean对象扩展机制的类关系,如图 7-3
ClassPathXmlApplicationContext
类的实现。而这个类就是最后交给用户使用的类。BeanFactoryPostProcessor
、BeanPostProcessor
两个接口,把关于对 Bean 的扩展机制串联进去了。cn.bugstack.springframework.beans.factory.config.BeanFactoryPostProcessor
public interface BeanFactoryPostProcessor { /** * 在全部的 BeanDefinition 加载完成后,实例化 Bean 对象以前,提供修改 BeanDefinition 属性的机制 * * @param beanFactory * @throws BeansException */ void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException; }
Allows for custom modification of an application context's bean definitions,adapting the bean property values of the context's underlying bean factory.
其实也就是说这个接口是知足于在全部的 BeanDefinition 加载完成后,实例化 Bean 对象以前,提供修改 BeanDefinition 属性的机制。cn.bugstack.springframework.beans.factory.config.BeanPostProcessor
public interface BeanPostProcessor { /** * 在 Bean 对象执行初始化方法以前,执行此方法 * * @param bean * @param beanName * @return * @throws BeansException */ Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; /** * 在 Bean 对象执行初始化方法以后,执行此方法 * * @param bean * @param beanName * @return * @throws BeansException */ Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
Factory hook that allows for custom modification of new bean instances,e.g. checking for marker interfaces or wrapping them with proxies.
也就是提供了修改新实例化 Bean 对象的扩展点。postProcessBeforeInitialization
用于在 Bean 对象执行初始化方法以前,执行此方法、postProcessAfterInitialization
用于在 Bean 对象执行初始化方法以后,执行此方法。cn.bugstack.springframework.context.ApplicationContext
public interface ApplicationContext extends ListableBeanFactory { }
cn.bugstack.springframework.context.ConfigurableApplicationContext
public interface ConfigurableApplicationContext extends ApplicationContext { /** * 刷新容器 * * @throws BeansException */ void refresh() throws BeansException; }
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. 在 Bean 实例化以前,执行 BeanFactoryPostProcessor (Invoke factory processors registered as beans in the context.) invokeBeanFactoryPostProcessors(beanFactory); // 4. BeanPostProcessor 须要提早于其余 Bean 对象实例化以前执行注册操做 registerBeanPostProcessors(beanFactory); // 5. 提早实例化单例Bean对象 beanFactory.preInstantiateSingletons(); } protected abstract void refreshBeanFactory() throws BeansException; protected abstract ConfigurableListableBeanFactory getBeanFactory(); private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class); for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()) { beanFactoryPostProcessor.postProcessBeanFactory(beanFactory); } } private void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class); for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) { beanFactory.addBeanPostProcessor(beanPostProcessor); } } //... getBean、getBeansOfType、getBeanDefinitionNames 方法 }
spring.xml
配置资源的加载。以后是在 refresh() 定义实现过程,包括:
cn.bugstack.springframework.context.support.AbstractRefreshableApplicationContext
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext { private DefaultListableBeanFactory beanFactory; @Override protected void refreshBeanFactory() throws BeansException { DefaultListableBeanFactory beanFactory = createBeanFactory(); loadBeanDefinitions(beanFactory); this.beanFactory = beanFactory; } private DefaultListableBeanFactory createBeanFactory() { return new DefaultListableBeanFactory(); } protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory); @Override protected ConfigurableListableBeanFactory getBeanFactory() { return beanFactory; } }
DefaultListableBeanFactory
的实例化以及对资源配置的加载操做 loadBeanDefinitions(beanFactory)
,在加载完成后便可完成对 spring.xml 配置文件中 Bean 对象的定义和注册,同时也包括实现了接口 BeanFactoryPostProcessor、BeanPostProcessor 的配置 Bean 信息。loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
,继续由其余抽象类继承实现。cn.bugstack.springframework.context.support.AbstractXmlApplicationContext
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext { @Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) { XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory, this); String[] configLocations = getConfigLocations(); if (null != configLocations){ beanDefinitionReader.loadBeanDefinitions(configLocations); } } protected abstract String[] getConfigLocations(); }
cn.bugstack.springframework.context.support.ClassPathXmlApplicationContext
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext { private String[] configLocations; public ClassPathXmlApplicationContext() { } /** * 从 XML 中加载 BeanDefinition,并刷新上下文 * * @param configLocations * @throws BeansException */ public ClassPathXmlApplicationContext(String configLocations) throws BeansException { this(new String[]{configLocations}); } /** * 从 XML 中加载 BeanDefinition,并刷新上下文 * @param configLocations * @throws BeansException */ public ClassPathXmlApplicationContext(String[] configLocations) throws BeansException { this.configLocations = configLocations; refresh(); } @Override protected String[] getConfigLocations() { return configLocations; } }
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); } addSingleton(beanName, bean); return bean; } public InstantiationStrategy getInstantiationStrategy() { return instantiationStrategy; } public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) { this.instantiationStrategy = instantiationStrategy; } private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) { // 1. 执行 BeanPostProcessor Before 处理 Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName); // 待完成内容:invokeInitMethods(beanName, wrappedBean, beanDefinition); invokeInitMethods(beanName, wrappedBean, beanDefinition); // 2. 执行 BeanPostProcessor After 处理 wrappedBean = applyBeanPostProcessorsAfterInitialization(bean, beanName); return wrappedBean; } private void invokeInitMethods(String beanName, Object wrappedBean, BeanDefinition beanDefinition) { } @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; } }
postProcessBeforeInitialization
、postProcessAfterInitialization
,分别做用于 Bean 对象执行初始化先后的额外处理。initializeBean(beanName, bean, beanDefinition);
操做。而这个操做主要主要是对于方法 applyBeanPostProcessorsBeforeInitialization
、applyBeanPostProcessorsAfterInitialization
的使用。AutowireCapableBeanFactory
中新增长的。cn.bugstack.springframework.test.bean.UserDao
public class UserDao { private static Map<String, String> hashMap = new HashMap<>(); static { hashMap.put("10001", "小傅哥"); hashMap.put("10002", "八杯水"); hashMap.put("10003", "阿毛"); } public String queryUserName(String uId) { return hashMap.get(uId); } }
cn.bugstack.springframework.test.bean.UserService
public class UserService { private String uId; private String company; private String location; private UserDao userDao; public void queryUserInfo() { return userDao.queryUserName(uId); } // ...get/set }
cn.bugstack.springframework.test.common.MyBeanFactoryPostProcessor
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService"); PropertyValues propertyValues = beanDefinition.getPropertyValues(); propertyValues.addPropertyValue(new PropertyValue("company", "改成:字节跳动")); } }
cn.bugstack.springframework.test.common.MyBeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if ("userService".equals(beanName)) { UserService userService = (UserService) bean; userService.setLocation("改成:北京"); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }
基础配置,无BeanFactoryPostProcessor、BeanPostProcessor,实现类
<?xml version="1.0" encoding="UTF-8"?> <beans> <bean id="userDao" class="cn.bugstack.springframework.test.bean.UserDao"/> <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>
加强配置,有BeanFactoryPostProcessor、BeanPostProcessor,实现类
<?xml version="1.0" encoding="UTF-8"?> <beans> <bean id="userDao" class="cn.bugstack.springframework.test.bean.UserDao"/> <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> <bean class="cn.bugstack.springframework.test.common.MyBeanPostProcessor"/> <bean class="cn.bugstack.springframework.test.common.MyBeanFactoryPostProcessor"/> </beans>
@Test public void test_BeanFactoryPostProcessorAndBeanPostProcessor(){ // 1.初始化 BeanFactory DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); // 2. 读取配置文件&注册Bean XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); reader.loadBeanDefinitions("classpath:spring.xml"); // 3. BeanDefinition 加载完成 & Bean实例化以前,修改 BeanDefinition 的属性值 MyBeanFactoryPostProcessor beanFactoryPostProcessor = new MyBeanFactoryPostProcessor(); beanFactoryPostProcessor.postProcessBeanFactory(beanFactory); // 4. Bean实例化以后,修改 Bean 属性信息 MyBeanPostProcessor beanPostProcessor = new MyBeanPostProcessor(); beanFactory.addBeanPostProcessor(beanPostProcessor); // 5. 获取Bean对象调用方法 UserService userService = beanFactory.getBean("userService", UserService.class); String result = userService.queryUserInfo(); System.out.println("测试结果:" + result); }
测试结果
测试结果:小傅哥,改成:字节跳动,改成:北京 Process finished with exit code 0
@Test public void test_xml() { // 1.初始化 BeanFactory ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:springPostProcessor.xml"); // 2. 获取Bean对象调用方法 UserService userService = applicationContext.getBean("userService", UserService.class); String result = userService.queryUserInfo(); System.out.println("测试结果:" + result); }
测试结果
测试结果:小傅哥,改成:字节跳动,改成:北京 Process finished with exit code 0
面试问那么多,但是工做又用不到,是嘎哈么呢?
,嘎哈么,那你说你开车上桥的时候,会每次都撞两边的护栏吗,不撞是吧,那不要修了哇,直接就铺一个平板,还省材料了。其实核心技术的原理学习,是更有助于你完成更复杂的架构设计,当你的知识能更全面覆盖所承接的需求时,也就能更好的作出合理的架构和落地。