目录

一、定义

二、自定义BeanPostProcessor的实现类

三、BeanPostProcessor的注册过程分析

四、BeanPostProcessor的执行过程分析

五、BeanPostProcessor的常用子类和实现类

六、总结


一、定义

BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口,它可以在Spring容器实例化bean之后,在执行bean的初始化方法前后,允许我们自定义修改新的bean实例,如修改bean的属性,可以给bean生成一个动态代理实例等等,Spring AOP的底层处理也是通过实现BeanPostProcessor来执行代理包装逻辑的。

BeanPostProcessor是一个接口,其定义如下:

public interface BeanPostProcessor {// 在实例化及依赖注入完成后、在bean初始化之前执行@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}// 在bean初始化之后执行@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}}

注意:接口中的两个方法都要将传入的bean返回,而不能返回null,如果返回的是null,那么会导致后面的BeanPostProcessor无法得到执行,也可能导致通过getBean方法得不到目标bean对象。

二、自定义BeanPostProcessor的实现类

  • (一)、先编写一个简单的实体类
public class Student implements Serializable, InitializingBean {private String id;private String name;private Integer age;public Student() {System.out.println("执行Student实例化...");}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public void init() {System.out.println("执行Student的init()方法...");}public void destroy() {System.out.println("执行Student的destroy()方法...");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("执行Student的afterPropertiesSet()方法...");}@Overridepublic String toString() {return "Student{" +"id='" + id + '\'' +", name='" + name + '\'' +", age=" + age +'}';}
}

这里,实体类实现了InitializingBean接口重写了afterPropertiesSet()方法,以及定义了两个自定义初始化、销毁对应的方法。

  • (二)、编写BeanPostProcessor实现类
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("执行MyBeanPostProcessor的postProcessBeforeInitialization()方法...");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("执行MyBeanPostProcessor的postProcessAfterInitialization()方法...");return bean;}
}

跟BeanFactoryPostProcessor一样,当定义多个BeanPostProcessor的时候,如果想要自定义各个BeanPostProcessor的执行顺序,也可以实现Orderd接口,执行order属性的值,order越小,优先级越高,BeanPostProcessor最先被执行。

  • (三)、编写spring配置文件,注册自定义的BeanFactoryPostProcessor、bean信息
<!--自定义BeanPostProcessor-->
<bean id="student" class="com.wsh.beanpostprocessor.Student" init-method="init" destroy-method="destroy"><property name="id" value="1"/><property name="name" value="张三"/><property name="age" value="10"/>
</bean>
<bean id="myBeanPostProcessor" class="com.wsh.beanpostprocessor.MyBeanPostProcessor"/>
  • (四)、测试类
public class Test {public static void main(String[] args) {ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-config.xml");System.out.println( applicationContext.getBean("student"));}
}
  • (五)、运行结果
执行Student实例化...
执行MyBeanPostProcessor的postProcessBeforeInitialization()方法...
执行Student的afterPropertiesSet()方法...
执行Student的init()方法...
执行MyBeanPostProcessor的postProcessAfterInitialization()方法...
Student{id='1', name='张三', age=10}

从上面的结果可以看出,在调用两个初始化方法前后,执行了自定义BeanPostProcessor的逻辑,这里只是简单的输出,读者可自行扩展。并且初始化方法的执行顺序是,先执行afterPropertiesSet(),再执行自定义的初始化方法init-method。

三、BeanPostProcessor的注册过程分析

BeanPostProcessor的注册是在refresh()方法的第六步完成的,主要通过registerBeanPostProcessors(beanFactory)方法:

/*** 6、注册BeanPostProcessor,注意,这里还不会执行BeanPostProcessor对应的增强方法*  真正调用是在bean初始化前、初始化后*/
registerBeanPostProcessors(beanFactory);// org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

可以看到,核心逻辑都委托给PostProcessorRegistrationDelegate的registerBeanPostProcessors()方法。

首先简述一下registerBeanPostProcessors()方法的处理过程:

  • 1、从bean工厂中获取到所有实现了BeanPostProcessor接口的bean;
  • 2、循环遍历扫描出的所有的BeanPostProcessor,然后分别存放到前面定义的几个集合中;
  • 3、按优先级排序后,注册实现了PriorityOrdered接口的BeanPostProcessor;
  • 4、按优先级排序后,注册实现了Ordered接口的BeanPostProcessor;
  • 5、注册其他普通的BeanPostProcessor;
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {// 1、从bean工厂中获取到所有实现了BeanPostProcessor接口的bean// 如本例中我们自定义的MyBeanPostProcessor就会在这里被扫描出String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);// Register BeanPostProcessorChecker that logs an info message when// a bean is created during BeanPostProcessor instantiation, i.e. when// a bean is not eligible for getting processed by all BeanPostProcessors.int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;// 往bean工厂中添加一个BeanPostProcessor -> BeanPostProcessorChecker// BeanPostProcessorChecker是一个在创建bean期间记录信息消息的BeanPostProcessorbeanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));// 存放实现了PriorityOrdered接口的BeanPostProcessorList<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();// 存放实现了MergedBeanDefinitionPostProcessor接口的BeanPostProcessorList<BeanPostProcessor> internalPostProcessors = new ArrayList<>();// 存放实现了Ordered接口的BeanPostProcessorList<String> orderedPostProcessorNames = new ArrayList<>();// 存放普通的BeanPostProcessorList<String> nonOrderedPostProcessorNames = new ArrayList<>();// 2、循环遍历扫描出的所有的BeanPostProcessor,然后分别存放到前面定义的几个集合中for (String ppName : postProcessorNames) {// 实现了PriorityOrdered接口的BeanPostProcessorif (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {// 通过getBean获取对应的Bean实例,然后添加到priorityOrderedPostProcessors集合中// 这里涉及到获取bean的过程,暂且不深入分析BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);priorityOrderedPostProcessors.add(pp);// 如果同时实现了MergedBeanDefinitionPostProcessor接口,加入到internalPostProcessors集合中if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {// 实现了Ordered接口的BeanPostProcessororderedPostProcessorNames.add(ppName);}else {// 普通BeanPostProcessornonOrderedPostProcessorNames.add(ppName);}}// 排序sortPostProcessors(priorityOrderedPostProcessors, beanFactory);// 3、注册实现了PriorityOrdered接口的BeanPostProcessorregisterBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();for (String ppName : orderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);orderedPostProcessors.add(pp);// 如果同时实现了MergedBeanDefinitionPostProcessor接口,加入到internalPostProcessors集合中if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}// 排序sortPostProcessors(orderedPostProcessors, beanFactory);// 4、注册实现了Ordered接口的BeanPostProcessor// 通过beanFactory.addBeanPostProcessor(postProcessor)添加BeanPostProcessorregisterBeanPostProcessors(beanFactory, orderedPostProcessors);// Now, register all regular BeanPostProcessors.// 5、注册其他普通的BeanPostProcessorList<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();for (String ppName : nonOrderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);nonOrderedPostProcessors.add(pp);// 如果同时实现了MergedBeanDefinitionPostProcessor接口,加入到internalPostProcessors集合中if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}// 通过beanFactory.addBeanPostProcessor(postProcessor)添加BeanPostProcessorregisterBeanPostProcessors(beanFactory, nonOrderedPostProcessors);// 排序sortPostProcessors(internalPostProcessors, beanFactory);// 通过beanFactory.addBeanPostProcessor(postProcessor)添加BeanPostProcessor// 6、注册所有内部 BeanPostProcessorregisterBeanPostProcessors(beanFactory, internalPostProcessors);// Re-register post-processor for detecting inner beans as ApplicationListeners,// moving it to the end of the processor chain (for picking up proxies etc).// 7、往bean工厂中添加一个BeanPostProcessor -> ApplicationListenerDetector// ApplicationListenerDetector主要是检测bean是否实现了ApplicationListener接口beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

真正的注册方法是在registerBeanPostProcessors():

// org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanPostProcessor>)
// 注册给定的BeanPostProcessor
private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {// 遍历给定的BeanPostProcessor集合,挨个通过addBeanPostProcessor方法,向bean工厂中添加,保存到BeanFactory的beanPostProcessors成员变量中// private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();for (BeanPostProcessor postProcessor : postProcessors) {beanFactory.addBeanPostProcessor(postProcessor);}
}

具体就是循环已经注册的BeanPostProcessor集合,通过beanFactory.addBeanPostProcessor添加,保存到BeanFactory的beanPostProcessors成员变量中:

private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();// org.springframework.beans.factory.support.AbstractBeanFactory#addBeanPostProcessor
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");// 如果当前beanPostProcessor已经存在,则先移除this.beanPostProcessors.remove(beanPostProcessor);// Track whether it is instantiation/destruction awareif (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {this.hasInstantiationAwareBeanPostProcessors = true;}if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {this.hasDestructionAwareBeanPostProcessors = true;}// 将beanPostProcessor添加到beanPostProcessors成员属性中// private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();this.beanPostProcessors.add(beanPostProcessor);
}

通过上述的处理,BeanPostProcessor已经完成了向bean工厂的注册工作,注意这里只是完成了注册,并没有执行BeanPostProcessor,真正执行是在bean初始化前、后。

四、BeanPostProcessor的执行过程分析

上图是Spring IOC容器刷新的简图,从图中可以看到,BeanPostProcessor的执行是在bean的初始化前、后执行,bean初始化之前会执行BeanPostProcessor的postProcessBeforeInitialization()方法,bean初始化之后会调用BeanPostProcessor的postProcessAfterInitialization()方法。

我们都知道,bean的初始化执行具体是在AbstractAutowireCapableBeanFactory#initializeBean(),下面我们就从

initializeBean()方法入手,看下BeanPostProcessor是如何执行的。

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {// 1、执行Aware方法,如BeanNameAware、BeanClassLoaderAware、BeanFactoryAwareif (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());} else {invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {// 2、执行BeanPostProcessor后置处理器的前置处理方法:postProcessBeforeInitialization(),允许对bean实例进行包装wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {// 3、执行初始化方法,包括InitializingBean的afterPropertiesSet()方法、自定义的初始化方法init-methodinvokeInitMethods(beanName, wrappedBean, mbd);} catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) {// 4、执行BeanPostProcessor后置处理器的后置处理方法:postProcessAfterInitialization(),允许对bean实例进行包装wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;
}

initializeBean()方法的执行流程还是很清晰的:

  • 1、执行Aware方法,如BeanNameAware、BeanClassLoaderAware、BeanFactoryAware;
  • 2、执行BeanPostProcessor后置处理器的前置处理方法:postProcessBeforeInitialization(),允许对bean实例进行包装;
  • 3、执行初始化方法,包括InitializingBean的afterPropertiesSet()方法、自定义的初始化方法init-method;
  • 4、执行BeanPostProcessor后置处理器的后置处理方法:postProcessAfterInitialization(),允许对bean实例进行包装;

从前面的代码中可以看到,BeanPostProcessor的执行确实是在bean执行初始化方法的前面、后面。

BeanPostProcessor的前置增强具体是在方法applyBeanPostProcessorsBeforeInitialization():

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;// 1、获取到当前工厂中注册的所有BeanPostProcessor后置处理器for (BeanPostProcessor processor : getBeanPostProcessors()) {// 2、执行每一个BeanPostProcessor的前置增强方法:postProcessBeforeInitialization()Object current = processor.postProcessBeforeInitialization(result, beanName);if (current == null) {// 3、如果postProcessBeforeInitialization()返回为空,则直接返回原始bean,将不会执行后续的BeanPostProcessor后置处理器的增强return result;}// 4、使用增强后的bean current,赋值给result,然后返回result = current;}return result;
}

BeanPostProcessor的后置增强具体是在方法applyBeanPostProcessorsAfterInitialization():

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;// 1、获取到工厂中注册的所有BeanPostProcessor后置增强器for (BeanPostProcessor processor : getBeanPostProcessors()) {// 2、执行BeanPostProcessor的后置增强方法postProcessAfterInitialization()Object current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {// 3、如果postProcessAfterInitialization()返回为空,则直接返回原始bean,将不会执行后续的BeanPostProcessor后置处理器的增强return result;}// 4、使用增强后的bean current,赋值给result,然后返回result = current;}return result;
}

上述就是BeanPostProcessor的具体执行过程,相对来说还是比较容易理解的。

五、BeanPostProcessor的常用子类和实现类

Spring中有内置的一些BeanPostProcessor实现类以及子类,例如:

  • (一)、InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口,可以在Bean生命周期的另外两个时期提供扩展的回调接口,即实例化Bean之前(调用postProcessBeforeInstantiation方法)和实例化Bean之后(调用postProcessAfterInstantiation方法),该接口定义如下:

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {// 1.在目标Bean实例化之前执行// 2.如果方法返回的是一个非空对象,将会跳过后续Spring默认的创建流程// 3.默认实现返回null@Nullabledefault Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return null;}// 1.在目标Bean实例化之后、属性填充前执行// 2.默认实现返回true// 3.如果方法返回false,将会跳过后续的属性填充过程,通常情况下都应该返回truedefault boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}// 允许对填充前的属性进行处理(如对属性的验证)@Nullabledefault PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)throws BeansException {return null;}// 对属性值进行修改,通过基于原始的PropertyValues创建一个新的MutablePropertyValues实例,添加或删除特定的值// 已标记过期方法,在spring未来版本可能会被删除,官方推荐使用postProcessProperties()方法@Deprecated@Nullabledefault PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;}}
  • (二)、ApplicationContextAwareProcessor:用来为bean注入ApplicationContext等容器对象

在postProcessBeforeInitialization()方法中通过invokeAwareInterfaces(bean)方法给目标bean注入指定的属性值:

public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {AccessControlContext acc = null;if (System.getSecurityManager() != null &&(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {acc = this.applicationContext.getBeanFactory().getAccessControlContext();}// 执行Aware接口if (acc != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareInterfaces(bean);return null;}, acc);}else {invokeAwareInterfaces(bean);}return bean;
}private void invokeAwareInterfaces(Object bean) {if (bean instanceof Aware) {// 给bean设置Environment属性if (bean instanceof EnvironmentAware) {((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());}// 给bean设置EmbeddedValueResolver属性if (bean instanceof EmbeddedValueResolverAware) {((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);}// 给bean设置ResourceLoader属性if (bean instanceof ResourceLoaderAware) {((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);}// 给bean设置ApplicationEventPublisher属性if (bean instanceof ApplicationEventPublisherAware) {((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);}// 给bean设置MessageSource属性if (bean instanceof MessageSourceAware) {((MessageSourceAware) bean).setMessageSource(this.applicationContext);}// 给bean设置ApplicationContext属性if (bean instanceof ApplicationContextAware) {((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);}}
}
  • (三)、ApplicationListenerDetector:判断目标bean是否是ApplicationListener类型, 如果是,则添加到事件多播器中

在postProcessAfterInitialization()方法中实现了注册应用监视器功能:

public Object postProcessAfterInitialization(Object bean, String beanName) {if (bean instanceof ApplicationListener) {// potentially not detected as a listener by getBeanNamesForType retrievalBoolean flag = this.singletonNames.get(beanName);if (Boolean.TRUE.equals(flag)) {// singleton bean (top-level or inner): register on the flythis.applicationContext.addApplicationListener((ApplicationListener<?>) bean);}else if (Boolean.FALSE.equals(flag)) {if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {// inner bean with other scope - can't reliably process eventslogger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +"but is not reachable for event multicasting by its containing ApplicationContext " +"because it does not have singleton scope. Only top-level listener beans are allowed " +"to be of non-singleton scope.");}this.singletonNames.remove(beanName);}}return bean;
}
  • (四)、CommonAnnotationBeanPostProcessor:支持@Resource注解的注入
  • (五)、AutowiredAnnotationBeanPostProcessor:支持@Autowired注解的注入
  • (六)、RequiredAnnotationBeanPostProcessor:支持@Required注解的注入

六、总结

总结一下BeanFactoryPostProcessor和BeanPostProcessor的区别,看下图:

  •  1、执行时机不同

BeanFactoryPostProcessor是在bean实例化之前,也就是bean还没调用构造方法创建对象之前调用;

BeanPostProcessor是在beanbean初始化之前、初始化之后进行调用,这时候bean已经完成了实例化和属性填充;

  • 2、处理对象不同

BeanFactoryPostProcessor是BeanFactory级别的处理,是针对整个Bean的工厂进行处理;

BeanPostProcessor是bean级别的处理,针对某个具体的bean进行处理;

  • 3、使用场景不同

BeanFactoryPostProcessor允许我们在实例化任何bean之前,读取bean的定义(配置元数据),然后修改它,或者往工厂中注入更多的bean定义;

BeanPostProcessor允许我们自定义修改新的bean实例,如修改bean的属性或者给bean生成一个动态代理的对象等等;

Spring扩展之BeanPostProcessor接口相关推荐

  1. Spring扩展之BeanPostProcessor

    作用 BeanPostProcessor,顾名思义是bean后置处理器,是 Spring 的扩展点之一.通过自定义 BeanPostProcessor 可以实现对 Bean 的修改,用于在bean实例 ...

  2. Spring中的BeanPostProcessor接口

    由方法名字也可以看出,前者在实例化及依赖注入完成后.在任何初始化代码(比如配置文件中的init-method)调用之前调用:后者在初始化代码调用之后调用. 注意: 1.接口中的两个方法都要将传入的be ...

  3. Spring BeanPostProcessor接口详细使用

    BeanPostProcessor接口简介 BeanPostProcessor也称为Bean后置处理器,它是Spring中定义的接口,在Spring容器的创建过程中(具体为Bean初始化前后)会回调B ...

  4. Spring系列(八):Spring生命周期中BeanPostProcessor接口用法介绍

    今天给大家介绍BeanPostProcessor接口用法,希望对大家能有所帮助! 1.BeanPostProcessor 概念介绍 BeanPostProcessor接口通常被称为Bean的后置处理器 ...

  5. Spring源码分析之BeanPostProcessor接口和BeanFactoryPostProcessor接口方法不执行原因分析

    首先下面是我的Bean /** Copyright 2002-2017 the original author or authors.** Licensed under the Apache Lice ...

  6. Spring后处理Bean(BeanPostProcessor 接口)Bean增强

    后处理Bean也称之为Bean的后处理器,作用是:在Bean初始化的前后,对Bean对象进行增强.它既可以增强一个指定的Bean,也可以增强所有的Bean,底层很多功能(如AOP等)的实现都是基于它的 ...

  7. Spring系列之BeanPostProcessor分析

    在Spring系列之Bean的生命周期及相关源码中,我们最后简单使用过BeanPostProcessor,这次我们就结合源码来具体谈谈这个BeanPostProcessor的作用. 实现BeanPos ...

  8. 深入理解BeanPostProcessor接口

    BeanPostProcessor提供了在bean初始化之前和之后插入自定义逻辑的能力.与BeanFactoryPostProcessor的区别是处理的对象不同,BeanFactoryPostProc ...

  9. 【小家Spring】注意BeanPostProcessor启动时对依赖Bean的“误伤”陷阱(is not eligible for getting processed by all...)

    每篇一句 祝大家五一国际劳动节快乐~你是在快乐的撸码,还是在快乐的浪呢? 本文已被https://yourbatman.cn收录:程序员专用网盘https://wangpan.yourbatman.c ...

  10. Spring扩展点总结

    经历了一系列复杂的spring应用后,你的项目可能已经用上注解,也用上了xxx.properties,你对这神奇的用法感到欣喜,但你不知道他是怎么被实现的,现在就让我们来揭开这些神秘的面纱. Bean ...

最新文章

  1. Linux下的find命令
  2. java资料——线性表(转)
  3. 使用MrBayes构建贝叶斯系统发育树【实践】
  4. Linux下的示例程序
  5. 机器学习入门学习笔记:(2.4)线性判别分析理论推导
  6. 算法—详细讲解双向链表的实现(python)
  7. Apple 的CEO 吹响了战斗的号角啦!
  8. ajax中dom,在(jQuery)ajax请求中获取当前脚本DOM对象
  9. declaration of 'int ret' shadows a parameter
  10. 命令 启动顺序_笔记一: 启动选项与系统变量
  11. 让linux的SSH客户端也能记住服务器的密码
  12. 华硕笔记本r414u怎么安装键盘_华硕笔记本键盘灯怎么开
  13. 在Mac下配置Macaca环境
  14. php 递归函数返回数组,php递归函数 PHP中Array相关函数简介
  15. 无向图的极大团、最大团(Bron-Kerbosch算法)
  16. 领英1度2度3度是什么意思,如何突破领英好友人脉限制
  17. 如何拥有一个免费云服务器
  18. 打印标签时如何解决打印偏移
  19. android so strip,用于CMake构建工具链中“strip”命令的Android NDK路径变量
  20. 王道数据结构p41——22

热门文章

  1. take android,Protake
  2. python %号_python基础集结号
  3. 计算机视觉图像去噪原理,AI笔记: 计算机视觉之图像滤波去噪: 原理、方法和效果比较...
  4. html页面显示代码插件,客户端显示web网页支持html5的第三方内核插件
  5. python 直线检测_python hough变换检测直线的实现方法
  6. Can Place Flowers
  7. 《基 于 N Gram 的无词典 中文分词算法》 n-gram读感
  8. HBASE table导出到文件的方法
  9. 算法萌新如何学好动态规划(一)
  10. 【 Codeforces Round #547 (Div. 3) G】Privatization of Roads in Treeland【树上贪心问题】