手写简版spring --6--应用上下文(BeanPostProcessor 和 BeanFactoryPostProcessor)
一、目标
如果你在自己的实际工作中开发过基于 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 框架上下文的处理能力,就可以满足我们的目标需求了。整体设计结构如下图:
- 满足于对 Bean 对象扩展的两个接口,其实也是 Spring 框架中非常具有重量级的两个接口:
BeanFactoryPostProcess 和 BeanPostProcessor
,也几乎是大家在使用 Spring框架额外新增开发自己组建需求的两个必备接口。- BeanFactoryPostProcessor,
是由Spring框架组建提供的容器扩展机制,允许在 Bean 对象注册后但未实例化之前,对 Bean 的定义信息 BeanDefinition 执行修改操作。
- BeanPostProcessor,也是 Spring 提供的扩展机制,不过
BeanPostProcessor 是在Bean 对象实例化之后修改 Bean 对象,也可以替换 Bean 对象。这部分与后面要实现的 AOP 有着密切的关系。
- 同时如果只是添加这两个接口,不做任何包装,那么对于使用者来说还是非常麻烦的。
我们希望于开发 Spring 的上下文操作类,把相应的 XML加载 、注册、实 例化以及新增的修改和扩展都融合进去,让 Spring 可以自动扫描到我们的新增服务,便于用户使用。
三、实现
- 工程结构
- 在整个类图中主要体现出来的是关于
Spring 应用上下文以及对 Bean 对象扩展机制的实现
。- 以继承了 ListableBeanFactory 接口的 ApplicationContext 接口开始,扩展出一系列应用上下文的抽象实现类,并最终完成ClassPathXmlApplicationContext 类的实现。而这个类就是最后交给用户使用的类。
- 同时在实现应用上下文的过程中,
通过定义接口:BeanFactoryPostProcessor、BeanPostProcessor 两个接口,把关于对 Bean 的扩展机制串联进去了。
- 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;
}
- 在 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 属性的机制。
- 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;
}
- 在 Spring 源码中有这样一段描述 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 对象执行初始化方法之后,执行此方法。
- 定义上下文接口
public interface ApplicationContext extends ListableBeanFactory {}
- context 是本次实现应用上下文功能新增的服务包
- 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 源码,那么一定会看到这个方法。
接下 来也是需要在上下文的实现中完成刷新容器的操作过程
- 应用上下文抽象类实现
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();}
}
- AbstractApplicationContext
继承 DefaultResourceLoader 是为了处理spring.xml 配置资源的加载
。- 之后是在 refresh() 定义实现过程,包括:
- 创建 BeanFactory ,并加载 BeanDefinition
- 获取 BeanFactory
- 在
Bean 实例化之前,执行 BeanFactoryPostProcessor
(Invoke factory processors registered as beans in the context.)BeanPostProcessor 需要提前于其他 Bean 对象实例化之前执行注册操作
提前实例化单例 Bean 对象
- 另外把定义出来的抽象方法, refreshBeanFactory() 、 getBeanFactory() 由后面的继承此抽象类的其他抽象类实现。
- 获取 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;}
}
- 在 refreshBeanFactory() 中主要是获取了
DefaultListableBeanFactory的实例化以及对资源配置的加载操作loadBeanDefinitions(beanFactory) beanFactory)
,在加载完成后即可完成对spring.xml 配置文件中 Bean 对象的定义和注册,同时也包括实现了接口BeanFactoryPostProcessor 、 BeanPostProcessor的配置 Bean 信息。
- 但此时资源加载还只是定义了
一个抽象类方法loadBeanDefinitions(DefaultListableBeanFactory beanFactory)beanFactory)
,继续由其他抽象类继承实现。
- 上下文中对配置信息的加载
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();
}
- 在 AbstractXmlApplicationContext 抽象类的 loadBeanDefinitions 方法实现中,
使用 XmlBeanDefinitionReader 类,处理了关于 XML 文件配置信息的操作。
- 同时这里又
留下了一个抽象类方法getConfigLocations()getConfigLocations(),此方法是为了从入口上下文类,拿到配置信息的地址描述。
- 应用上下文实现类 (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;}
}
- ClassPathXmlApplicationContext ,是具体对外给用户提供的应用上下文方法。
- 在
继承了 AbstractXmlApplicationContext 以及层层抽象类 的功能分离实现后,在此类 ClassPathXmlApplicationContext 的实现中就简单多了
,主要是对继承抽象类中方法的调用和提供了配置文件地址信息。
- 在 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;}
}
- 实现 BeanPostProcessor 接口后,会涉及到两个接口方法,
postProcessBeforeInitialization 、postProcessAfterInitialization ,分别作用于 Bean 对象执行初始化前后的额外处理。
- 也就是需要在创建 Bean 对象时,
在 createBean 方法中添加initializeBean(beanName, bean, beanDefinition); 操作
。而这个操作主要主要是对于方法applyBeanPostProcessorsBeforeInitialization 、applyBeanPostProces sorsAfterInitialization 的使用。- 另外需要提一下
,applyBeanPostProcessorsBeforeInitialization 、applyBeanPostProcessorsAfterInitialization 两个方法是在接口类 AutowireCapableBeanFactory 中新增加的。
四、测试
- 事先准备
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;}
}
- Dao 、 Service ,是我们平常开发经常使用的场景。在 UserService 中注入UserDao ,这样就能体现出 Bean 属性的依赖了。
- 另外这里
新增加了 company 、 location ,两个属性信息,便于测试BeanPostProcessor 、 BeanFactoryPostProcessor 两个接口对 Bean 属性信息扩展的作用。
- 实现 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;}
}
- 如果你在 Spring 中做过一些组件的开发那么一定非常熟悉这两个类,本文的测试也是
实现了这两个类,对实例化过程中的 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>
- 这里提供了两个配置文件,一个是不包含 BeanFactoryPostProcessor 、BeanPostProcessor ,另外一个是包含的。
之所以这样配置主要对照验证,在运用Spring 新增加的应用上下文和不使用的时候,都是怎么操作的。
- 不用应用上下文
@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);}
- DefaultListableBeanFactory
创建 beanFactory 并使用 XmlBeanDefinitionReader加载配置文件的方式
,还是比较熟悉的。- 接下来就是对 MyBeanFactoryPostProcessor 和 MyBeanPostProcessor 的处理,
一个是在 BeanDefinition 加载完成 & Bean 实例化之前,修改 BeanDefinition 的属性值,另外一个是在 Bean 实例化之后,修改 Bean 属性信息。
- 使用应用上下文
@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);}
- 使用新增加的 ClassPathXmlApplicationContext 应用上下文类,再操作起来就方便多了,
这才是面向用户使用的类 ,在这里可以一步把配置文件交给ClassPathXmlApplicationContext ,也不需要管理一些自定义实现的 Spring 接口的类。
上面两个的测试结果是一样的,不过使用应用上下文的方式明显更加方便
五、总结
- 本文主要新增了 Spring 框架中两个非常重要的接口 BeanFactoryPostProcess 、BeanPostProcessor 同时还添加了关于应用上下文的实现,
ApplicationContext 接口的定义是继承 BeanFactory 外新增加功能的接口,它可以满足于自动识别、资源加载、容器事件、监听器等功能,同时例如一些国际化支持、单例 Bean 自动初始化等,也是可以在这个类里实现和扩充的。
- 通过本文的实现一定会非常了解 BeanFactoryPostProcess 、 BeanPostProcessor ,
以后再做一些关于 Spring 中间件的开发时,如果需要用到 Bean 对象的获取以及修改一些属性信息,那么就可以使用这两个接口了。同时 BeanPostProcessor 也是实现 AOP 切面技术的关键所在。
手写简版spring --6--应用上下文(BeanPostProcessor 和 BeanFactoryPostProcessor)相关推荐
- 手写简版spring --10--容器事件和事件监听器
一.降低耦合 解耦场景在互联网开发的设计中使用的也是非常频繁,如:这里需要一个注册完成事件推送消息.用户下单我会发送一个MQ.收到我的支付消息就可以发货了等等,都是依靠事件订阅和发布以及MQ消息这样的 ...
- 手写简版spring --9--对象作用域和FactoryBean
一.目标 交给 Spring 管理的 Bean 对象,一定就是我们用类创建出来的 Bean 吗?创建出来的 Bean 就永远是单例的吗,没有可能是原型模式吗?在集合 Spring 框架下,我们使用的 ...
- 手写简版spring --2--实现Bean的定义、注册、获取
一.目标 在上一章节我们初步依照 Spring Bean 容器的概念,实现了一个粗糙版本的代码实现.那么本章节我们需要结合已实现的 Spring Bean 容器进行功能完善,实现 Bean 容器关于 ...
- 手写简版spring --1--创建简单的Bean容器
一.声明 这个系列是我自己的学习笔记,为了在学习的过程中巩固知识而记录的,好强迫自己用心拜读,而不是进收藏夹.本系列都是基于小缚哥的文章和代码的,想要深入了解,请移步小缚哥博客 二.spring-Be ...
- 手写简版spring --8--Aware感知容器对象Aware感知容器对象
一.目标 目前已实现的 Spring 框架,在 Bean 操作上能提供出的能力,包括:Bean 对象的定义和注册,以及在操作 Bean 对象过程中执行的,BeanFactoryPostProcesso ...
- 手写简版spring --7--初始化方法和销毁方法
一.目标 当我们的类创建的 Bean 对象,交给 Spring 容器管理以后,这个类对象就可以被赋予更多的使用能力.就像我们在上一章节已经给类对象添加了修改注册Bean定义未实例化前的属性信息修改和实 ...
- 手写简版spring --5--资源加载器解析文件注册对象
一.目标 在完成 Spring 的框架雏形后,现在我们可以通过单元测试进行手动操作Bean对象的定义.注册和属性填充,以及最终获取对象调用方法.但这里会有一个问题,就是如果实际使用这个 Spring ...
- 手写简版spring --4--注入属性和依赖对象
一.目标 首先我们回顾下这几章节都完成了什么,包括:实现一个容器.定义和注册Bean.实例化Bean,按照是否包含构造函数实现不同的实例化策略,那么在创建对象实例化这我们还缺少什么?其实还缺少一个关于 ...
- 手写简版spring --3--对象实例化策略
一.目标 这一章节的目标主要是为了解决上一章节我们埋下的坑,那是什么坑呢?其实就是一个关于 Bean 对象在含有构造函数进行实例化的坑.在上一章节我们扩充了 Bean 容器的功能,把实例化对象交给容器 ...
最新文章
- Docker入门与实践
- ubuntu的java环境变量_Ubuntu安装JDK与环境变量配置
- Knative 健康检查机制分析
- html条件查询的页面,如何在 url 中记录页面搜索条件
- 德佑地产房产经纪人区域总监访谈:掌门的态度
- ubuntu 以太网已连接但是无法联网_5G物联网掀起工业自动化新高潮 连接器需求巨大...
- mysql concat键值对_mysql中concat函数实现数据库字段合并查询
- HTC Vive凭什么在十分钟内获得1.5万的订单?
- [MySQL] InnoDB三大特性之 - 插入缓冲
- React + leaflet 地图瓦片 加载错乱 不能正常显示
- 计算机c盘快满了怎么办,电脑C盘满了怎么办?教你快速清理C盘的垃圾
- Jmeter 压测工具使用手册(完整版)
- 计算机三级单片机及应用技术,08秋计算机等级考试试卷(三级+单片机及应用技术)...
- React 移动端`1px`像素边框
- android 音频系统/声卡驱动 codec
- 1024为大家带来个猜数字游戏
- Apache Doris在京东广告的应用
- 特别有趣的spyder运行程序
- 距离度量与相似度度量
- 来自Jeff和Joel对Stack Overflow网站建设的教训(摘选)
热门文章
- OWIN的理解和实践(三) –Middleware开发入门
- Leetcode-937-Reorder Log Files-(Easy)
- linux下的ps命令
- Compiling Cpp(zz)
- LeetCode-Majority Element II
- 两经纬度之间的距离计算
- Httpclient 实现带参文件上传
- 论文笔记:NEUROVASCULAR COUPLING AND EPILEPSY: HEMODYNAMIC MARKERS
- 不同版本GCC编译器之间的切换
- 科学计算:Python VS. MATLAB (1)----给我一个理由先