一、目标

如果你在自己的实际工作中开发过基于 Spring 的技术组件,或者学习过关于SpringBoot 中间件设计和开发等内容。那么你一定会继承或者实现了 Spring对外暴露的类或接口,在接口的实现中获取了 BeanFactory 以及 Bean 对象的获取等内容,并对这些内容做一些操作,例如:修改 Bean 的信息,添加日志打印、处理数据库路由对数据源的切换、给 RPC 服务连接注册中心等。在对容器中 Bean 的实例化过程添加扩展机制的同时,还需要把目前关于Spring.xml 初始化和加载策略进行优化,因为我们不太可能让面向 Spring 本身开发的 DefaultListableBeanFactory 服务,直接给予用户使用。修改点如下:

  • DefaultListableBeanFactory、XmlBeanDefinitionReader,是我们在目前 Spring 框架中对于服务功能测试的使用方式,它能很好的体现出 Spring 是如何对 xml 加载以及注册Bean 对象的操作过程,但这种方式是面向 Spring 本身的,还不具备一定的扩展性。
  • 就像我们现在需要提供出一个可以在 Bean 初始化过程中,完成对 Bean 对象的扩展时,就很难做到自动化处理。所以我们要把 Bean 对象扩展机制功能和对Spring 框架上下文的包装融合起来,对外提供完整的服务。

二、设计

为了能满足于在 Bean 对象从注册到实例化的过程中执行用户的自定义操作,就需要在 Bean 的定义和初始化过程中插入接口类,这个接口再有外部去实现自己需要的服务。那么在结合对 Spring 框架上下文的处理能力,就可以满足我们的目标需求了。整体设计结构如下图:

  1. 满足于对 Bean 对象扩展的两个接口,其实也是 Spring 框架中非常具有重量级的两个接口:BeanFactoryPostProcess 和 BeanPostProcessor,也几乎是大家在使用 Spring框架额外新增开发自己组建需求的两个必备接口。
  2. BeanFactoryPostProcessor,是由Spring框架组建提供的容器扩展机制,允许在 Bean 对象注册后但未实例化之前,对 Bean 的定义信息 BeanDefinition 执行修改操作。
  3. BeanPostProcessor,也是 Spring 提供的扩展机制,不过 BeanPostProcessor 是在Bean 对象实例化之后修改 Bean 对象,也可以替换 Bean 对象。这部分与后面要实现的 AOP 有着密切的关系。
  4. 同时如果只是添加这两个接口,不做任何包装,那么对于使用者来说还是非常麻烦的。我们希望于开发 Spring 的上下文操作类,把相应的 XML加载 、注册、实 例化以及新增的修改和扩展都融合进去,让 Spring 可以自动扫描到我们的新增服务,便于用户使用。

三、实现

  1. 工程结构

  1. 在整个类图中主要体现出来的是关于 Spring 应用上下文以及对 Bean 对象扩展机制的实现
  2. 以继承了 ListableBeanFactory 接口的 ApplicationContext 接口开始,扩展出一系列应用上下文的抽象实现类,并最终完成ClassPathXmlApplicationContext 类的实现。而这个类就是最后交给用户使用的类。
  3. 同时在实现应用上下文的过程中,通过定义接口:BeanFactoryPostProcessor、BeanPostProcessor 两个接口,把关于对 Bean 的扩展机制串联进去了。
  1. BeanFactoryPostProcessor:是由 Spring 框架组建提供的容器扩展机制,允许在Bean 对象注册后但未实例化之前,对 Bean 的定义信息 BeanDefinition 执行修改操作。在spring源码中,针对的是BeanFactory的扩展,可以在容器启动时修改bean的定义。
//允许自定义修改 BeanDefinition 属性信息
public interface BeanFactoryPostProcessor {/*** 在所有的 BeanDefinition 加载完成后,实例化 Bean 对象之前,提供修改 BeanDefinition 属性的机制* @param beanFactory* @throws BeansException*/void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
  1. 在 Spring 源码中有这样一段描述 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 属性的机制。
  1. BeanPostProcessor:,也是 Spring 提供的扩展机制,不过 BeanPostProcessor 是在Bean 对象实例化之后修改 Bean 对象,也可以替换 Bean 对象(AOP)。在spring源码中属于bean级别的处理,针对某个具体的bean进行处理接口提供了两个方法,分别是初始化前和初始化后执行方法,具体这个初始化方法指的是什么方法,类似我们在定义bean时,定义了init-method所指定的方法这两个方法分别在init方法前后执行,需要注意一点,我们定义一个类实现了BeanPostProcessor,默认是会对整个Spring容器中所有的bean进行处理。
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;
}
  1. 在 Spring 源码中有这样一段描述 Factory hook that allows for custom modification of new bean instances,e.g. checking
    for marker interfaces or wrapping them with proxies. 也就是提供了修改新实例化 Bean 对象的扩展点
  2. 另外此接口提供了两个方法: postProcessBeforeInitialization 用于在Bean 对象执行初始化方法之前,执行此方法、 postProcessAfterInitialization 用于在 Bean 对象执行初始化方法之后,执行此方法。
  1. 定义上下文接口
public interface ApplicationContext extends ListableBeanFactory {}
  1. context 是本次实现应用上下文功能新增的服务包
  2. ApplicationContext ,继承于 ListableBeanFactory ,也就继承了关于 BeanFactory方法,比如一些 getBean 的方法。另外 ApplicationContext 本身是 Central 接口,但目前还不需要添加一些获取 ID 和父类上下文,所以暂时没有接口方法的定义。
public interface ConfigurableApplicationContext extends ApplicationContext {/*** 刷新容器* @throws BeansException*/void refresh() throws BeansException;void registerShutdownHook();void close();
}

ConfigurableApplicationContext 继承自 ApplicationContext ,并提供了 refresh 这个核心方法。 如果你有看过一些 Spring 源码,那么一定会看到这个方法。 接下 来也是需要在上下文的实现中完成刷新容器的操作过程

  1. 应用上下文抽象类实现
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {@Overridepublic void refresh() throws BeansException {// 1. 创建 BeanFactory,并加载 BeanDefinitionrefreshBeanFactory();// 2. 获取 BeanFactoryConfigurableListableBeanFactory 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);}}@Overridepublic <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {return getBeanFactory().getBeansOfType(type);}@Overridepublic String[] getBeanDefinitionNames() {return getBeanFactory().getBeanDefinitionNames();}@Overridepublic Object getBean(String name) throws BeansException {return getBeanFactory().getBean(name);}@Overridepublic Object getBean(String name, Object... args) throws BeansException {return getBeanFactory().getBean(name, args);}@Overridepublic <T> T getBean(String name, Class<T> requiredType) throws BeansException {return getBeanFactory().getBean(name, requiredType);}@Overridepublic void registerShutdownHook() {Runtime.getRuntime().addShutdownHook(new Thread(this::close));}@Overridepublic void close() {getBeanFactory().destroySingletons();}
}
  1. AbstractApplicationContext 继承 DefaultResourceLoader 是为了处理spring.xml 配置资源的加载
  2. 之后是在 refresh() 定义实现过程,包括:
  1. 创建 BeanFactory ,并加载 BeanDefinition
  2. 获取 BeanFactory
  3. Bean 实例化之前,执行 BeanFactoryPostProcessor (Invoke factory processors registered as beans in the context.)
  4. BeanPostProcessor 需要提前于其他 Bean 对象实例化之前执行注册操作
  5. 提前实例化单例 Bean 对象
  1. 另外把定义出来的抽象方法, refreshBeanFactory() 、 getBeanFactory() 由后面的继承此抽象类的其他抽象类实现。
  1. 获取 Bean 工厂和加载资源
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {private DefaultListableBeanFactory beanFactory;@Overrideprotected void refreshBeanFactory() throws BeansException {DefaultListableBeanFactory beanFactory = createBeanFactory();loadBeanDefinitions(beanFactory);this.beanFactory = beanFactory;}private DefaultListableBeanFactory createBeanFactory() {return new DefaultListableBeanFactory();}protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory);@Overrideprotected ConfigurableListableBeanFactory getBeanFactory() {return beanFactory;}
}
  1. 在 refreshBeanFactory() 中主要是获取了 DefaultListableBeanFactory的实例化以及对资源配置的加载操作loadBeanDefinitions(beanFactory) beanFactory),在加载完成后即可完成对spring.xml 配置文件中 Bean 对象的定义和注册,同时也包括实现了接口BeanFactoryPostProcessor 、 BeanPostProcessor的配置 Bean 信息。
  2. 但此时资源加载还只是定义了一个抽象类方法loadBeanDefinitions(DefaultListableBeanFactory beanFactory)beanFactory),继续由其他抽象类继承实现。
  1. 上下文中对配置信息的加载
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext {@Overrideprotected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory, this);String[] configLocations = getConfigLocations();if (null != configLocations){beanDefinitionReader.loadBeanDefinitions(configLocations);}}protected abstract String[] getConfigLocations();
}
  1. 在 AbstractXmlApplicationContext 抽象类的 loadBeanDefinitions 方法实现中,使用 XmlBeanDefinitionReader 类,处理了关于 XML 文件配置信息的操作。
  2. 同时这里又留下了一个抽象类方法getConfigLocations()getConfigLocations(),此方法是为了从入口上下文类,拿到配置信息的地址描述。
  1. 应用上下文实现类 (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();}@Overrideprotected String[] getConfigLocations() {return configLocations;}
}
  1. ClassPathXmlApplicationContext ,是具体对外给用户提供的应用上下文方法。
  2. 继承了 AbstractXmlApplicationContext 以及层层抽象类 的功能分离实现后,在此类 ClassPathXmlApplicationContext 的实现中就简单多了,主要是对继承抽象类中方法的调用和提供了配置文件地址信息。
  1. 在 Bean 创建时完成前置和后置处理
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();@Overrideprotected 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;}protected void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition) {if (bean instanceof DisposableBean || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())) {registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition));}}protected Object createBeanInstance(BeanDefinition beanDefinition, String beanName, Object[] args) {Constructor constructorToUse = null;Class<?> beanClass = beanDefinition.getBeanClass();Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();for (Constructor ctor : declaredConstructors) {if (null != args && ctor.getParameterTypes().length == args.length) {constructorToUse = ctor;break;}}return getInstantiationStrategy().instantiate(beanDefinition, beanName, constructorToUse, args);}/*** Bean 属性填充*/protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) {try {PropertyValues propertyValues = beanDefinition.getPropertyValues();for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {String name = propertyValue.getName();Object value = propertyValue.getValue();if (value instanceof BeanReference) {// A 依赖 B,获取 B 的实例化BeanReference beanReference = (BeanReference) value;value = getBean(beanReference.getBeanName());}// 属性填充BeanUtil.setFieldValue(bean, name, value);}} catch (Exception e) {throw new BeansException("Error setting property values:" + beanName);}}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);// 执行 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;}private void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {// 1. 实现接口 InitializingBeanif (bean instanceof InitializingBean) {((InitializingBean) bean).afterPropertiesSet();}// 2. 注解配置 init-method {判断是为了避免二次执行销毁}String initMethodName = beanDefinition.getInitMethodName();if (StrUtil.isNotEmpty(initMethodName)) {Method initMethod = beanDefinition.getBeanClass().getMethod(initMethodName);if (null == initMethod) {throw new BeansException("Could not find an init method named '" + initMethodName + "' on bean with name '" + beanName + "'");}initMethod.invoke(bean);}}@Overridepublic 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;}@Overridepublic 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;}
}
  1. 实现 BeanPostProcessor 接口后,会涉及到两个接口方法,postProcessBeforeInitialization 、postProcessAfterInitialization ,分别作用于 Bean 对象执行初始化前后的额外处理。
  2. 也就是需要在创建 Bean 对象时,在 createBean 方法中添加initializeBean(beanName, bean, beanDefinition); 操作。而这个操作主要主要是对于方法applyBeanPostProcessorsBeforeInitialization 、applyBeanPostProces sorsAfterInitialization 的使用。
  3. 另外需要提一下,applyBeanPostProcessorsBeforeInitialization 、applyBeanPostProcessorsAfterInitialization 两个方法是在接口类 AutowireCapableBeanFactory 中新增加的。

四、测试

  1. 事先准备
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 InitializingBean, DisposableBean {private String uId;private String company;private String location;private UserDao userDao;@Overridepublic void destroy() throws Exception {System.out.println("执行:UserService.destroy");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("执行:UserService.afterPropertiesSet");}public String queryUserInfo() {return userDao.queryUserName(uId) + "," + company + "," + location;}public String getuId() {return uId;}public void setuId(String uId) {this.uId = uId;}public String getCompany() {return company;}public void setCompany(String company) {this.company = company;}public String getLocation() {return location;}public void setLocation(String location) {this.location = location;}public UserDao getUserDao() {return userDao;}public void setUserDao(UserDao userDao) {this.userDao = userDao;}
}
  1. Dao 、 Service ,是我们平常开发经常使用的场景。在 UserService 中注入UserDao ,这样就能体现出 Bean 属性的依赖了。
  2. 另外这里新增加了 company 、 location ,两个属性信息,便于测试BeanPostProcessor 、 BeanFactoryPostProcessor 两个接口对 Bean 属性信息扩展的作用。
  1. 实现 BeanPostProcessor 和 BeanFactoryPostProcessor
//注册后实例化前对beandefinifion修改
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");PropertyValues propertyValues = beanDefinition.getPropertyValues();propertyValues.addPropertyValue(new PropertyValue("company", "改为:字节跳动"));}
}
//实例化后对userService进行修改
public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if ("userService".equals(beanName)) {UserService userService = (UserService) bean;userService.setLocation("改为:北京");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}
}
  1. 如果你在 Spring 中做过一些组件的开发那么一定非常熟悉这两个类,本文的测试也是实现了这两个类,对实例化过程中的 Bean 对象做一些操作。
  1. 配置文件

基础配置,无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>
  1. 这里提供了两个配置文件,一个是不包含 BeanFactoryPostProcessor 、BeanPostProcessor ,另外一个是包含的。之所以这样配置主要对照验证,在运用Spring 新增加的应用上下文和不使用的时候,都是怎么操作的。
  1. 不用应用上下文
    @Testpublic void test_BeanFactoryPostProcessorAndBeanPostProcessor(){// 1.初始化 BeanFactoryDefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();// 2. 读取配置文件&注册BeanXmlBeanDefinitionReader 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);}
  1. DefaultListableBeanFactory 创建 beanFactory 并使用 XmlBeanDefinitionReader加载配置文件的方式,还是比较熟悉的。
  2. 接下来就是对 MyBeanFactoryPostProcessor 和 MyBeanPostProcessor 的处理,一个是在 BeanDefinition 加载完成 & Bean 实例化之前,修改 BeanDefinition 的属性值,另外一个是在 Bean 实例化之后,修改 Bean 属性信息。
  1. 使用应用上下文
@Testpublic void test_xml() {// 1.初始化 BeanFactoryClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:springPostProcessor.xml");// 2. 获取Bean对象调用方法UserService userService = applicationContext.getBean("userService", UserService.class);String result = userService.queryUserInfo();System.out.println("测试结果:" + result);}
  1. 使用新增加的 ClassPathXmlApplicationContext 应用上下文类,再操作起来就方便多了, 这才是面向用户使用的类 ,在这里可以一步把配置文件交给ClassPathXmlApplicationContext ,也不需要管理一些自定义实现的 Spring 接口的类。

上面两个的测试结果是一样的,不过使用应用上下文的方式明显更加方便

五、总结

  1. 本文主要新增了 Spring 框架中两个非常重要的接口 BeanFactoryPostProcess 、BeanPostProcessor 同时还添加了关于应用上下文的实现, ApplicationContext 接口的定义是继承 BeanFactory 外新增加功能的接口,它可以满足于自动识别、资源加载、容器事件、监听器等功能,同时例如一些国际化支持、单例 Bean 自动初始化等,也是可以在这个类里实现和扩充的。
  2. 通过本文的实现一定会非常了解 BeanFactoryPostProcess 、 BeanPostProcessor ,以后再做一些关于 Spring 中间件的开发时,如果需要用到 Bean 对象的获取以及修改一些属性信息,那么就可以使用这两个接口了。同时 BeanPostProcessor 也是实现 AOP 切面技术的关键所在。

手写简版spring --6--应用上下文(BeanPostProcessor 和 BeanFactoryPostProcessor)相关推荐

  1. 手写简版spring --10--容器事件和事件监听器

    一.降低耦合 解耦场景在互联网开发的设计中使用的也是非常频繁,如:这里需要一个注册完成事件推送消息.用户下单我会发送一个MQ.收到我的支付消息就可以发货了等等,都是依靠事件订阅和发布以及MQ消息这样的 ...

  2. 手写简版spring --9--对象作用域和FactoryBean

    一.目标 交给 Spring 管理的 Bean 对象,一定就是我们用类创建出来的 Bean 吗?创建出来的 Bean 就永远是单例的吗,没有可能是原型模式吗?在集合 Spring 框架下,我们使用的 ...

  3. 手写简版spring --2--实现Bean的定义、注册、获取

    一.目标 在上一章节我们初步依照 Spring Bean 容器的概念,实现了一个粗糙版本的代码实现.那么本章节我们需要结合已实现的 Spring Bean 容器进行功能完善,实现 Bean 容器关于 ...

  4. 手写简版spring --1--创建简单的Bean容器

    一.声明 这个系列是我自己的学习笔记,为了在学习的过程中巩固知识而记录的,好强迫自己用心拜读,而不是进收藏夹.本系列都是基于小缚哥的文章和代码的,想要深入了解,请移步小缚哥博客 二.spring-Be ...

  5. 手写简版spring --8--Aware感知容器对象Aware感知容器对象

    一.目标 目前已实现的 Spring 框架,在 Bean 操作上能提供出的能力,包括:Bean 对象的定义和注册,以及在操作 Bean 对象过程中执行的,BeanFactoryPostProcesso ...

  6. 手写简版spring --7--初始化方法和销毁方法

    一.目标 当我们的类创建的 Bean 对象,交给 Spring 容器管理以后,这个类对象就可以被赋予更多的使用能力.就像我们在上一章节已经给类对象添加了修改注册Bean定义未实例化前的属性信息修改和实 ...

  7. 手写简版spring --5--资源加载器解析文件注册对象

    一.目标 在完成 Spring 的框架雏形后,现在我们可以通过单元测试进行手动操作Bean对象的定义.注册和属性填充,以及最终获取对象调用方法.但这里会有一个问题,就是如果实际使用这个 Spring ...

  8. 手写简版spring --4--注入属性和依赖对象

    一.目标 首先我们回顾下这几章节都完成了什么,包括:实现一个容器.定义和注册Bean.实例化Bean,按照是否包含构造函数实现不同的实例化策略,那么在创建对象实例化这我们还缺少什么?其实还缺少一个关于 ...

  9. 手写简版spring --3--对象实例化策略

    一.目标 这一章节的目标主要是为了解决上一章节我们埋下的坑,那是什么坑呢?其实就是一个关于 Bean 对象在含有构造函数进行实例化的坑.在上一章节我们扩充了 Bean 容器的功能,把实例化对象交给容器 ...

最新文章

  1. Docker入门与实践
  2. ubuntu的java环境变量_Ubuntu安装JDK与环境变量配置
  3. Knative 健康检查机制分析
  4. html条件查询的页面,如何在 url 中记录页面搜索条件
  5. 德佑地产房产经纪人区域总监访谈:掌门的态度
  6. ubuntu 以太网已连接但是无法联网_5G物联网掀起工业自动化新高潮 连接器需求巨大...
  7. mysql concat键值对_mysql中concat函数实现数据库字段合并查询
  8. HTC Vive凭什么在十分钟内获得1.5万的订单?
  9. [MySQL] InnoDB三大特性之 - 插入缓冲
  10. React + leaflet 地图瓦片 加载错乱 不能正常显示
  11. 计算机c盘快满了怎么办,电脑C盘满了怎么办?教你快速清理C盘的垃圾
  12. Jmeter 压测工具使用手册(完整版)
  13. 计算机三级单片机及应用技术,08秋计算机等级考试试卷(三级+单片机及应用技术)...
  14. React 移动端`1px`像素边框
  15. android 音频系统/声卡驱动 codec
  16. 1024为大家带来个猜数字游戏
  17. Apache Doris在京东广告的应用
  18. 特别有趣的spyder运行程序
  19. 距离度量与相似度度量
  20. 来自Jeff和Joel对Stack Overflow网站建设的教训(摘选)

热门文章

  1. OWIN的理解和实践(三) –Middleware开发入门
  2. Leetcode-937-Reorder Log Files-(Easy)
  3. linux下的ps命令
  4. Compiling Cpp(zz)
  5. LeetCode-Majority Element II
  6. 两经纬度之间的距离计算
  7. Httpclient 实现带参文件上传
  8. 论文笔记:NEUROVASCULAR COUPLING AND EPILEPSY: HEMODYNAMIC MARKERS
  9. 不同版本GCC编译器之间的切换
  10. 科学计算:Python VS. MATLAB (1)----给我一个理由先