Skip to content

Commit

Permalink
1. 整理好自定义标签解析文章
Browse files Browse the repository at this point in the history
2. 分析 beanFactory 的后处理器 完成,详细搜索 注释 6.
  • Loading branch information
Vip-Augus committed Jun 16, 2019
1 parent 4bfb08b commit 226ee34
Show file tree
Hide file tree
Showing 17 changed files with 589 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [ClassPathXmlApplicationContext](#classpathxmlapplicationcontext)
- [设置配置文件路径](#设置配置文件路径)
- [Profile](#profile)
Expand Down Expand Up @@ -31,9 +33,9 @@
**展示的代码摘取了一些核心方法,去掉一些默认设置和日志输出,还有大多数错误异常也去掉了,小伙伴想看详细代码,注释和
demo,可以下载我上传的笔记项目📒**

[码云 Gitee 地址](https://gitee.com/vip-augus/spring-analysis-note.git)
[spring-analysis-note 码云 Gitee 地址](https://gitee.com/vip-augus/spring-analysis-note.git)

[Github 地址](https://github.com/Vip-Augus/spring-analysis-note)
[spring-analysis-note Github 地址](https://github.com/Vip-Augus/spring-analysis-note)

通过阅读源码的过程,了解设计者的设计思路和从中学习,对 `spring`
有个基础的了解。
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@

再次说下,下载项目看完整注释,跟着源码一起分析\~

[码云 Gitee 地址](https://gitee.com/vip-augus/spring-analysis-note.git)
[spring-analysis-note 码云 Gitee 地址](https://gitee.com/vip-augus/spring-analysis-note.git)

[Github 地址](https://github.com/Vip-Augus/spring-analysis-note)
[spring-analysis-note Github 地址](https://github.com/Vip-Augus/spring-analysis-note)

------------------------------------------------------------------------

Expand Down
423 changes: 423 additions & 0 deletions spring-analysis-note/note/2019-06-16-spring-analysis-note-3.md

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package context;

import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
* 注释 6.3 BeanFactory 后处理器的 demo
* @author JingQ at 2019-06-14
*/
public class BeanFactoryPostProcessorBootstrap {

public static void main(String[] args) {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("factory.bean/factory-post-processor.xml");
BeanFactoryPostProcessor beanFactoryPostProcessor = (BeanFactoryPostProcessor) context.getBean("carPostProcessor");
beanFactoryPostProcessor.postProcessBeanFactory(context.getBeanFactory());
// 输出 :Car{maxSpeed=0, brand='*****', price=10000.0},敏感词被替换了
System.out.println(context.getBean("car"));

// 硬编码 后处理器执行时间
BeanFactoryPostProcessor hardCodeBeanFactoryPostProcessor = new HardCodeBeanFactoryPostProcessor();
context.addBeanFactoryPostProcessor(hardCodeBeanFactoryPostProcessor);
// 更新上下文
context.refresh();
// 输出 :
// Hard Code BeanFactory Post Processor execute time
// Car{maxSpeed=0, brand='*****', price=10000.0}
System.out.println(context.getBean("car"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package context;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionVisitor;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.util.StringValueResolver;

import java.util.Set;

/**
* @author JingQ at 2019-06-14
*/
public class CarBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

/**
* 敏感词
*/
private Set<String> obscenties;

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 从 beanFactory 中获取 bean 名字列表
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
StringValueResolver valueResolver = strVal -> {
if (isObscene(strVal)) return "*****";
return strVal;
};
BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
// 这一步才是真正处理 bean 的配置信息
visitor.visitBeanDefinition(definition);
}

}

/**
* 判断 value 是否在敏感词列表中
* @param value 值
* @return boolean
*/
private boolean isObscene(Object value) {
String potentialObscenity = value.toString().toUpperCase();
return this.obscenties.contains(potentialObscenity);
}

public Set<String> getObscenties() {
return obscenties;
}

public void setObscenties(Set<String> obscenties) {
this.obscenties = obscenties;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package context;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

/**
* @author JingQ at 2019-06-16
*/
public class HardCodeBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("Hard Code BeanFactory Post Processor execute time");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="carPostProcessor" class="context.CarBeanFactoryPostProcessor">
<property name="obscenties">
<!--set 属性-->
<set>
<value>奔驰</value>
<value>特斯拉</value>
</set>
</property>
</bean>

<bean id="car" class="base.factory.bean.Car">
<property name="price" value="10000"/>
<property name="brand" value="奔驰"/>
</bean>

</beans>
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ protected BeanDefinitionVisitor() {
/**
* Traverse the given BeanDefinition object and the MutablePropertyValues
* and ConstructorArgumentValues contained in them.
*
* 遍历给定的 BeanDefinition 对象和其中包含的 MutablePropertyValues 和 ConstructorArgumentValues
* 在这一步中修改 beanDefinition 元数据
*
* @param beanDefinition the BeanDefinition object to traverse
* @see #resolveStringValue(String)
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
* <p>Application contexts can auto-detect BeanFactoryPostProcessor beans in
* their bean definitions and apply them before any other beans get created.
*
* 应用程序上下文可以自动检测bean定义中的BeanFactoryPostProcessor bean,并在创建任何其他bean之前应用它们。
*
* <p>Useful for custom config files targeted at system administrators that
* override bean properties configured in the application context.
*
Expand All @@ -37,6 +39,11 @@
* If bean instance interaction is required, consider implementing
* {@link BeanPostProcessor} instead.
*
* BeanFactoryPostProcessor 可以与 bean 定义交互并修改 bean 定义,
* 但绝不可以修改 bean 实例。这样做可能会导致过早的 bean 实例化,
* 破坏容器并导致意想不到的副作用。如果需要bean实例交互,则
* 考虑实现 BeanPostProcessor。
*
* @author Juergen Hoeller
* @since 06.07.2003
* @see BeanPostProcessor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,15 @@ public int getOrder() {
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 注释 6.2 属性资源 Configure
try {
// 合并
Properties mergedProps = mergeProperties();

// Convert the merged properties, if necessary.
// Convert the merged properties, if necessary. 转换
convertProperties(mergedProps);

// Let the subclass process the properties.
// Let the subclass process the properties. 让子类实现具体逻辑,修改 beanFactory 中的配置元数据
processProperties(beanFactory, mergedProps);
}
catch (IOException ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public BeanDefinition parse(Element element, ParserContext parserContext) {
*/
@Nullable
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
// 用 <myName:product> 为例子,localName 就是 product,是标签后面跟着的元素,根据这个元素,找到我们自定义的解析器
String localName = parserContext.getDelegate().getLocalName(element);
BeanDefinitionParser parser = this.parsers.get(localName);
if (parser == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ public interface ConfigurableApplicationContext extends ApplicationContext, Life
* Add a new BeanFactoryPostProcessor that will get applied to the internal
* bean factory of this application context on refresh, before any of the
* bean definitions get evaluated. To be invoked during context configuration.
*
* 添加一个新的 BeanFactoryPostProcessor,它将在刷新时应用于此应用程序上下文的内部 bean 工厂,然后再计算任何 bean 定义。在上下文配置期间调用。
*
* @param postProcessor the factory processor to register
*/
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
/**
* Create a new AnnotationConfigApplicationContext, scanning for bean definitions
* in the given packages and automatically refreshing the context.
*
* 创建一个新的AnnotationConfigApplicationContext,扫描给定包中的 bean 定义并自动刷新上下文
*
* @param basePackages the packages to check for annotated classes
*/
public AnnotationConfigApplicationContext(String... basePackages) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -526,9 +526,11 @@ public void refresh() throws BeansException, IllegalStateException {

try {
// Allows post-processing of the bean factory in context subclasses.
// 允许在上下文子类中对 bean工厂 进行后处理,要求在子类中实现该方法
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
// 注释 6.1 注册并执行 beanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
Expand Down Expand Up @@ -598,6 +600,7 @@ protected void prepareRefresh() {
}

// Initialize any placeholder property sources in the context environment.
// 在上下文环境中初始化任何占位符属性源
initPropertySources();

// Validate that all properties marked as required are resolvable:
Expand Down Expand Up @@ -651,6 +654,7 @@ protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

// Configure the bean factory with context callbacks.
// 这一步中,给 beanFactory 注册了个 beanPostProcessor,后处理器的类型是 ApplicationContextAwareProcessor
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public static void invokeBeanFactoryPostProcessors(

// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
// beanFactory 默认使用的是 DefaultListableBeanFactory,
// beanFactory 默认使用的是 DefaultListableBeanFactory,属于 BeanDefinitionRegistry
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 两个后处理器列表
Expand All @@ -83,6 +83,7 @@ public static void invokeBeanFactoryPostProcessors(
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 首先,调用实现 priorityOrder 的 beanDefinition 这就是前面提到过的优先级概念,这一步跟下面的优先级不一样之处,这一步的优先级是带有权重
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
Expand All @@ -91,7 +92,7 @@ public static void invokeBeanFactoryPostProcessors(
processedBeans.add(ppName);
}
}
// 对后处理器进行排序,主要看
// 对后处理器进行排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
Expand All @@ -107,10 +108,11 @@ public static void invokeBeanFactoryPostProcessors(
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 执行 definitionRegistryPostProcessor 接口的方法 :postProcessBeanDefinitionRegistry
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();

// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.最后,调用所有其他后处理器,直到不再出现其他 bean 为止
boolean reiterate = true;
while (reiterate) {
reiterate = false;
Expand All @@ -129,6 +131,7 @@ public static void invokeBeanFactoryPostProcessors(
}

// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 执行 postProcessBeanFactory 回调方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
Expand All @@ -140,6 +143,8 @@ public static void invokeBeanFactoryPostProcessors(

// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// 不要在这里初始化 factoryBean:我们需要保留所有常规 bean 未初始化,以便让 bean 工厂后处理程序应用于它们
// 注释 6.4 在这个步骤中,我们自定义的 carBeanFactoryPostProcessor 才真正注册并执行
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

Expand All @@ -164,10 +169,12 @@ else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
}

// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
// 首先执行的是带有权重顺序的后处理器
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
// 下一步执行普通顺序的后处理器
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
Expand All @@ -176,6 +183,7 @@ else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

// Finally, invoke all other BeanFactoryPostProcessors.
// 最后执行的是普通的后处理器
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
Expand All @@ -184,6 +192,7 @@ else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {

// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
// 清除缓存的合并bean定义,因为后处理程序可能已经修改了原始元数据,例如替换值中的占位符
beanFactory.clearMetadataCache();
}

Expand Down

0 comments on commit 226ee34

Please sign in to comment.