diff --git a/README.md b/README.md index 3e2e9e7..fe0b8ed 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ * [将 BeanDefinition 注册进 IoC 容器](/docs/Spring/IoC/3、将BeanDefinition注册进IoC容器.md) * [依赖注入(DI)](/docs/Spring/IoC/4、依赖注入(DI).md) * [BeanPostProcessor](/docs/Spring/IoC/BeanPostProcessor.md) +* [Spring BeanFactory源码解析](/docs/Spring/clazz/Spring-beanFactory.md) ### AOP @@ -67,6 +68,9 @@ * [Spring-import注解](/docs/Spring/clazz/Spring-Import.md) * [Spring-定时任务](/docs/Spring/clazz/Spring-Scheduling.md) * [Spring StopWatch](/docs/Spring/clazz/Spring-StopWatch.md) +* [Spring 元数据](/docs/Spring/clazz/Spring-Metadata.md) +* [Spring 条件接口](/docs/Spring/clazz/Spring-Conditional.md) + ### Spring5 新特性 @@ -89,6 +93,7 @@ * [SpringBoot 自动装配](/docs/SpringBoot/SpringBoot-自动装配.md) * [SpringBoot ConfigurationProperties](/docs/SpringBoot/SpringBoot-ConfigurationProperties.md) * [SpringBoot 日志系统](/docs/SpringBoot/SpringBoot-LogSystem.md) +* [SpringBoot ConditionalOnBean](/docs/SpringBoot/SpringBoot-ConditionalOnBean.md) ## MyBatis @@ -216,6 +221,12 @@ * [深挖 Redis 6.0 源码——SDS](docs/Redis/redis-sds.md) + +## Nacos + +* [nacos 服务注册](docs/nacos/nacos-discovery.md) + + ## 番外篇(JDK 1.8) ### 基础类库 * [String类 源码赏析](docs/JDK/basic/String.md) diff --git a/docs/Spring/clazz/Spring-Conditional.md b/docs/Spring/clazz/Spring-Conditional.md new file mode 100644 index 0000000..f0469e3 --- /dev/null +++ b/docs/Spring/clazz/Spring-Conditional.md @@ -0,0 +1,301 @@ +# Spring Conditional +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read) + + + +## Conditional + +```java +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Conditional { + + /** + * 多个匹配器接口 + */ + Class[] value(); + +} +``` + + + +## Condition + +``` +@FunctionalInterface +public interface Condition { + + /** + * 匹配,如果匹配返回true进行初始化,返回false跳过初始化 + */ + boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata); + +} +``` + + + +- ConditionContext 上下文 +- AnnotatedTypeMetadata 注解信息 + +### ConditionContext + +``` +public interface ConditionContext { + + /** + * bean的定义 + */ + BeanDefinitionRegistry getRegistry(); + + /** + * bean 工厂 + */ + @Nullable + ConfigurableListableBeanFactory getBeanFactory(); + + /** + * 环境 + */ + Environment getEnvironment(); + + /** + * 资源加载器 + */ + ResourceLoader getResourceLoader(); + + /** + * 类加载器 + */ + @Nullable + ClassLoader getClassLoader(); + +} +``` + +- 唯一实现 : `org.springframework.context.annotation.ConditionEvaluator.ConditionContextImpl` + + + +- 构造方法 + +```java +public ConditionContextImpl(@Nullable BeanDefinitionRegistry registry, + @Nullable Environment environment, @Nullable ResourceLoader resourceLoader) { + + this.registry = registry; + this.beanFactory = deduceBeanFactory(registry); + this.environment = (environment != null ? environment : deduceEnvironment(registry)); + this.resourceLoader = (resourceLoader != null ? resourceLoader : deduceResourceLoader(registry)); + this.classLoader = deduceClassLoader(resourceLoader, this.beanFactory); +} +``` + +- 在构造方法中加载了一些变量, 这些变量是根据一定规则转换后得到. 具体规则不展开. + + + + + + + +### AnnotatedTypeMetadata + +- 元数据接口 + +```java +public interface AnnotatedTypeMetadata { + + /** + * 获取所有注解 + */ + MergedAnnotations getAnnotations(); + + /** + * 是否有注解 + */ + default boolean isAnnotated(String annotationName) { + return getAnnotations().isPresent(annotationName); + } + + /** + * 获取注解的属性 + */ + @Nullable + default Map getAnnotationAttributes(String annotationName) { + return getAnnotationAttributes(annotationName, false); + } + +} +``` + + + + + +## 源码分析 + +- 对应测试类`org.springframework.context.annotation.ConfigurationClassWithConditionTests` + +```java +@Test +public void conditionalOnMissingBeanMatch() throws Exception { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(BeanOneConfiguration.class, BeanTwoConfiguration.class); + ctx.refresh(); + assertThat(ctx.containsBean("bean1")).isTrue(); + assertThat(ctx.containsBean("bean2")).isFalse(); + assertThat(ctx.containsBean("configurationClassWithConditionTests.BeanTwoConfiguration")).isFalse(); +} + + + + @Configuration + static class BeanOneConfiguration { + + @Bean + public ExampleBean bean1() { + return new ExampleBean(); + } + } + + @Configuration + @Conditional(NoBeanOneCondition.class) + static class BeanTwoConfiguration { + + @Bean + public ExampleBean bean2() { + return new ExampleBean(); + } + } + + + static class NoBeanOneCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return !context.getBeanFactory().containsBeanDefinition("bean1"); + } + } + +``` + + + + + + + +- `org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean` + + + + + + + + + +### shouldSkip + + + +```java +public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) { + if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) { + return false; + } + + if (phase == null) { + if (metadata instanceof AnnotationMetadata && + ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) { + return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION); + } + return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN); + } + + List conditions = new ArrayList<>(); + // 获取注解 Conditional 的属性值 + for (String[] conditionClasses : getConditionClasses(metadata)) { + for (String conditionClass : conditionClasses) { + // 序列化成注解 + Condition condition = getCondition(conditionClass, this.context.getClassLoader()); + // 插入注解列表 + conditions.add(condition); + } + } + + AnnotationAwareOrderComparator.sort(conditions); + + for (Condition condition : conditions) { + ConfigurationPhase requiredPhase = null; + if (condition instanceof ConfigurationCondition) { + requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase(); + } + + // matches 进行验证 + if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) { + return true; + } + } + + return false; +} +``` + + + + + +- 读取注解信息, 并且执行注解对应的类的方法 + + 用例如下. 实例化`BeanTwoConfiguration`对象的时候会去执行`NoBeanOneCondition`方法 + + ```java + @Configuration + @Conditional(NoBeanOneCondition.class) + static class BeanTwoConfiguration { + + @Bean + public ExampleBean bean2() { + return new ExampleBean(); + } + } + + + static class NoBeanOneCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return !context.getBeanFactory().containsBeanDefinition("bean1"); + } + } + ``` + + 在开发中可以自定义matches规则 + + + + + + + +这也是在注册的时候第一个方法 + +```java +private void doRegisterBean(Class beanClass, @Nullable String name, + @Nullable Class[] qualifiers, @Nullable Supplier supplier, + @Nullable BeanDefinitionCustomizer[] customizers) { + + AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); + // 和条件注解相关的函数 + if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { + return; + } + + // 省略其他 +} +``` \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-Metadata.md b/docs/Spring/clazz/Spring-Metadata.md new file mode 100644 index 0000000..371b0ef --- /dev/null +++ b/docs/Spring/clazz/Spring-Metadata.md @@ -0,0 +1,996 @@ +# Spring 元信息 + +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-Spring](https://github.com/SourceHot/spring-framework-read) + + +## ClassMetadata + + + + +```java +public interface ClassMetadata { + + /** + * 类名 + */ + String getClassName(); + + /** + * 是否是接口 + */ + boolean isInterface(); + + /** + * 是否是注解 + */ + boolean isAnnotation(); + + /** + * 是否是超类 + */ + boolean isAbstract(); + + /** + * 是否允许创建,实例化 + */ + default boolean isConcrete() { + return !(isInterface() || isAbstract()); + } + + /** + * 是否有final修饰 + */ + boolean isFinal(); + + /** + * 是否独立 + */ + boolean isIndependent(); + + /** + * 是否有内部类 + */ + default boolean hasEnclosingClass() { + return (getEnclosingClassName() != null); + } + + /** + * 是否是基础类 + */ + @Nullable + String getEnclosingClassName(); + + /** + * 是否有父类 + */ + default boolean hasSuperClass() { + return (getSuperClassName() != null); + } + + /** + * 父类名称 + */ + @Nullable + String getSuperClassName(); + + /** + * 实现类名称列表 + */ + String[] getInterfaceNames(); + + /** + * 成员列表 + * @since 3.1 + */ + String[] getMemberClassNames(); + +} +``` + + + + + +![image-20200824094154847](/images/spring/image-20200824094154847.png) + + + + + +## AnnotatedTypeMetadata + + + +```java +public interface AnnotatedTypeMetadata { + + /** + * 获取所有注解 + */ + MergedAnnotations getAnnotations(); + + /** + * 是否有注解 + */ + default boolean isAnnotated(String annotationName) { + return getAnnotations().isPresent(annotationName); + } + + /** + * 获取注解的属性 + */ + @Nullable + default Map getAnnotationAttributes(String annotationName) { + return getAnnotationAttributes(annotationName, false); + } + // 省略其他 + +} +``` + + + + +## AnnotationMetadata + +```java +public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata { + + /** + * 获取注解名称,全类名 + */ + default Set getAnnotationTypes() { + return getAnnotations().stream() + .filter(MergedAnnotation::isDirectlyPresent) + .map(annotation -> annotation.getType().getName()) + .collect(Collectors.toCollection(LinkedHashSet::new)); + } + + /** + * 注解全类名 + */ + default Set getMetaAnnotationTypes(String annotationName) { + MergedAnnotation annotation = getAnnotations().get(annotationName, MergedAnnotation::isDirectlyPresent); + if (!annotation.isPresent()) { + return Collections.emptySet(); + } + return MergedAnnotations.from(annotation.getType(), SearchStrategy.INHERITED_ANNOTATIONS).stream() + .map(mergedAnnotation -> mergedAnnotation.getType().getName()) + .collect(Collectors.toCollection(LinkedHashSet::new)); + } + + /** + * 是否包含某个注解 + */ + default boolean hasAnnotation(String annotationName) { + return getAnnotations().isDirectlyPresent(annotationName); + } + + /** + * 是否被某个注解标记过 + */ + default boolean hasMetaAnnotation(String metaAnnotationName) { + return getAnnotations().get(metaAnnotationName, + MergedAnnotation::isMetaPresent).isPresent(); + } + + /** + * 是否有注解,类里面有一个注解就返回true + */ + default boolean hasAnnotatedMethods(String annotationName) { + return !getAnnotatedMethods(annotationName).isEmpty(); + } + + /** + * 获取包含注解的方法 + */ + Set getAnnotatedMethods(String annotationName); + + + /** + * 通过反射创建一个注解的元信息 + */ + static AnnotationMetadata introspect(Class type) { + return StandardAnnotationMetadata.from(type); + } + +} +``` + + + + + + + +## MethodMetadata + +```java +public interface MethodMetadata extends AnnotatedTypeMetadata { + + /** + * 方法名称 + */ + String getMethodName(); + + /** + * 方法全路径 + */ + String getDeclaringClassName(); + + /** + * 返回值类型 + */ + String getReturnTypeName(); + + /** + * 是不是abstrac修饰 + */ + boolean isAbstract(); + + /** + * 是否 static 修饰 + */ + boolean isStatic(); + + /** + * 是否 final 修饰 + */ + boolean isFinal(); + + /** + * 是否重载 + */ + boolean isOverridable(); + +} +``` + + + + + + + +## MetadataReader + +```java +public interface MetadataReader { + + /** + * Return the resource reference for the class file. + * + * 获取资源 + */ + Resource getResource(); + + /** + * Read basic class metadata for the underlying class. + * 获取类的元信息 + */ + ClassMetadata getClassMetadata(); + + /** + * Read full annotation metadata for the underlying class, + * including metadata for annotated methods. + * + * 获取注解的元信息 + */ + AnnotationMetadata getAnnotationMetadata(); + +} +``` + + + + + +## MetadataReaderFactory + +- 用来创建 MetadataReader + +```java +public interface MetadataReaderFactory { + + /** + * Obtain a MetadataReader for the given class name. + * @param className the class name (to be resolved to a ".class" file) + * @return a holder for the ClassReader instance (never {@code null}) + * @throws IOException in case of I/O failure + */ + MetadataReader getMetadataReader(String className) throws IOException; + + /** + * Obtain a MetadataReader for the given resource. + * @param resource the resource (pointing to a ".class" file) + * @return a holder for the ClassReader instance (never {@code null}) + * @throws IOException in case of I/O failure + */ + MetadataReader getMetadataReader(Resource resource) throws IOException; + +} +``` + + + +- 接口解释的差不多了.接下来看一些实现 + + + + + +## StandardClassMetadata + +- 通过JAVA 反射来获取类的元信息 + +- 这个类采用的方式是Java class的方法,通过构造方法来填写一个Class对象. 之后使用这个对象的方法 + + + + + +```java +public class StandardClassMetadata implements ClassMetadata { + + private final Class introspectedClass; + + @Deprecated + public StandardClassMetadata(Class introspectedClass) { + Assert.notNull(introspectedClass, "Class must not be null"); + this.introspectedClass = introspectedClass; + } + + /** + * Return the underlying Class. + */ + public final Class getIntrospectedClass() { + return this.introspectedClass; + } + + + @Override + public String getClassName() { + return this.introspectedClass.getName(); + } + + @Override + public boolean isInterface() { + return this.introspectedClass.isInterface(); + } + + @Override + public boolean isAnnotation() { + return this.introspectedClass.isAnnotation(); + } + + @Override + public boolean isAbstract() { + return Modifier.isAbstract(this.introspectedClass.getModifiers()); + } + + @Override + public boolean isFinal() { + return Modifier.isFinal(this.introspectedClass.getModifiers()); + } + + @Override + public boolean isIndependent() { + return (!hasEnclosingClass() || + (this.introspectedClass.getDeclaringClass() != null && + Modifier.isStatic(this.introspectedClass.getModifiers()))); + } + + @Override + @Nullable + public String getEnclosingClassName() { + Class enclosingClass = this.introspectedClass.getEnclosingClass(); + return (enclosingClass != null ? enclosingClass.getName() : null); + } + + @Override + @Nullable + public String getSuperClassName() { + Class superClass = this.introspectedClass.getSuperclass(); + return (superClass != null ? superClass.getName() : null); + } + + @Override + public String[] getInterfaceNames() { + Class[] ifcs = this.introspectedClass.getInterfaces(); + String[] ifcNames = new String[ifcs.length]; + for (int i = 0; i < ifcs.length; i++) { + ifcNames[i] = ifcs[i].getName(); + } + return ifcNames; + } + + @Override + public String[] getMemberClassNames() { + LinkedHashSet memberClassNames = new LinkedHashSet<>(4); + for (Class nestedClass : this.introspectedClass.getDeclaredClasses()) { + memberClassNames.add(nestedClass.getName()); + } + return StringUtils.toStringArray(memberClassNames); + } + +} +``` + + + + + +## StandardMethodMetadata + +- 通过java反射获取方法的元信息 +- 构造方法传递一个method + - 如果这个方法有注解,会进行注解的解析 + + + +```java +public class StandardMethodMetadata implements MethodMetadata { + + private final Method introspectedMethod; + + private final boolean nestedAnnotationsAsMap; + + private final MergedAnnotations mergedAnnotations; + + @Deprecated + public StandardMethodMetadata(Method introspectedMethod) { + this(introspectedMethod, false); + } + + + @Deprecated + public StandardMethodMetadata(Method introspectedMethod, boolean nestedAnnotationsAsMap) { + Assert.notNull(introspectedMethod, "Method must not be null"); + this.introspectedMethod = introspectedMethod; + this.nestedAnnotationsAsMap = nestedAnnotationsAsMap; + this.mergedAnnotations = MergedAnnotations.from( + introspectedMethod, SearchStrategy.DIRECT, RepeatableContainers.none()); + } + + + @Override + public MergedAnnotations getAnnotations() { + return this.mergedAnnotations; + } + + /** + * Return the underlying Method. + */ + public final Method getIntrospectedMethod() { + return this.introspectedMethod; + } + + @Override + public String getMethodName() { + return this.introspectedMethod.getName(); + } + + @Override + public String getDeclaringClassName() { + return this.introspectedMethod.getDeclaringClass().getName(); + } + + @Override + public String getReturnTypeName() { + return this.introspectedMethod.getReturnType().getName(); + } + + @Override + public boolean isAbstract() { + return Modifier.isAbstract(this.introspectedMethod.getModifiers()); + } + + @Override + public boolean isStatic() { + return Modifier.isStatic(this.introspectedMethod.getModifiers()); + } + + @Override + public boolean isFinal() { + return Modifier.isFinal(this.introspectedMethod.getModifiers()); + } + + @Override + public boolean isOverridable() { + return !isStatic() && !isFinal() && !isPrivate(); + } + + private boolean isPrivate() { + return Modifier.isPrivate(this.introspectedMethod.getModifiers()); + } + + @Override + @Nullable + public Map getAnnotationAttributes(String annotationName, boolean classValuesAsString) { + if (this.nestedAnnotationsAsMap) { + return MethodMetadata.super.getAnnotationAttributes(annotationName, classValuesAsString); + } + return AnnotatedElementUtils.getMergedAnnotationAttributes(this.introspectedMethod, + annotationName, classValuesAsString, false); + } + + /** + * 获取所有注解的信息 + */ + @Override + @Nullable + public MultiValueMap getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) { + if (this.nestedAnnotationsAsMap) { + return MethodMetadata.super.getAllAnnotationAttributes(annotationName, classValuesAsString); + } + return AnnotatedElementUtils.getAllAnnotationAttributes(this.introspectedMethod, + annotationName, classValuesAsString, false); + } + +} +``` + + + +## StandardAnnotationMetadata + +- StandardAnnotationMetadata是StandardClassMetadata的子类 + +- 还是一个基于JAVA 反射做的一个类 + + + +- 获取注解属性map + +```java +@Override +@Nullable +public Map getAnnotationAttributes(String annotationName, boolean classValuesAsString) { + if (this.nestedAnnotationsAsMap) { + return AnnotationMetadata.super.getAnnotationAttributes(annotationName, classValuesAsString); + } + return AnnotatedElementUtils.getMergedAnnotationAttributes( + getIntrospectedClass(), annotationName, classValuesAsString, false); +} +``` + +- `org.springframework.core.annotation.AnnotatedElementUtils#getMergedAnnotationAttributes(java.lang.reflect.AnnotatedElement, java.lang.String, boolean, boolean)` + - `org.springframework.core.annotation.AnnotatedElementUtils#getAnnotationAttributes` + - `org.springframework.core.annotation.MergedAnnotation#asAnnotationAttributes` + + + +```java +@Nullable +public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element, + String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap) { + + MergedAnnotation mergedAnnotation = getAnnotations(element) + .get(annotationName, null, MergedAnnotationSelectors.firstDirectlyDeclared()); + return getAnnotationAttributes(mergedAnnotation, classValuesAsString, nestedAnnotationsAsMap); +} +``` + + + +- 查看这个方法的源码借助测试类`org.springframework.core.annotation.AnnotatedElementUtilsTests#getMergedAnnotationAttributesOnClassWithLocalAnnotation` +- getAnnotations() 方法 + + + + + +### getAnnotations + +- `org.springframework.core.annotation.MergedAnnotations#from(java.lang.reflect.AnnotatedElement, org.springframework.core.annotation.MergedAnnotations.SearchStrategy, org.springframework.core.annotation.RepeatableContainers)` + - `org.springframework.core.annotation.TypeMappedAnnotations#from(java.lang.reflect.AnnotatedElement, org.springframework.core.annotation.MergedAnnotations.SearchStrategy, org.springframework.core.annotation.RepeatableContainers, org.springframework.core.annotation.AnnotationFilter)` + + + +- 最终我们找到的代码如下 + +```java +static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy, + RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) { + + if (AnnotationsScanner.isKnownEmpty(element, searchStrategy)) { + return NONE; + } + return new TypeMappedAnnotations(element, searchStrategy, repeatableContainers, annotationFilter); +} +``` + + + +- 判断是否为空. 为空返回None,不会为空构造出一个对象org.springframework.core.annotation.TypeMappedAnnotations + + + + + +### MergedAnnotations + + + + + +```java +public interface MergedAnnotations extends Iterable> { + + //确定注解是否存在 + boolean isPresent(Class annotationType); + //注解是否直接存在 + boolean isDirectlyPresent(Class annotationType); + // 获取匹配的注解 + MergedAnnotation get(Class annotationType); + // 省略其他 + +} +``` + +- 这个接口中还有两个方法 + + 1. `of` + 将多个`MergedAnnotations`合并 + + 2. `from` + + 将多个注解合并 + + + + + + + +### SearchStrategy + +```java +enum SearchStrategy { + + /** + * Find only directly declared annotations, without considering + * {@link Inherited @Inherited} annotations and without searching + * superclasses or implemented interfaces. + * + * 直接查找 + */ + DIRECT, + + /** + * Find all directly declared annotations as well as any + * {@link Inherited @Inherited} superclass annotations. This strategy + * is only really useful when used with {@link Class} types since the + * {@link Inherited @Inherited} annotation is ignored for all other + * {@linkplain AnnotatedElement annotated elements}. This strategy does + * not search implemented interfaces. + * + * 继承查找 + */ + INHERITED_ANNOTATIONS, + + /** + * Find all directly declared and superclass annotations. This strategy + * is similar to {@link #INHERITED_ANNOTATIONS} except the annotations + * do not need to be meta-annotated with {@link Inherited @Inherited}. + * This strategy does not search implemented interfaces. + * 查找当前类和父类的注解 + */ + SUPERCLASS, + + /** + * Perform a full search of the entire type hierarchy, including + * superclasses and implemented interfaces. Superclass annotations do + * not need to be meta-annotated with {@link Inherited @Inherited}. + */ + TYPE_HIERARCHY, + + /** + * Perform a full search of the entire type hierarchy on the source + * and any enclosing classes. This strategy is similar to + * {@link #TYPE_HIERARCHY} except that {@linkplain Class#getEnclosingClass() + * enclosing classes} are also searched. Superclass annotations do not + * need to be meta-annotated with {@link Inherited @Inherited}. When + * searching a {@link Method} source, this strategy is identical to + * {@link #TYPE_HIERARCHY}. + */ + TYPE_HIERARCHY_AND_ENCLOSING_CLASSES +} +``` + + + + + +- `org.springframework.core.annotation.TypeMappedAnnotations#get(java.lang.String, java.util.function.Predicate>, org.springframework.core.annotation.MergedAnnotationSelector)` + +```java +@Override +public MergedAnnotation get(String annotationType, + @Nullable Predicate> predicate, + @Nullable MergedAnnotationSelector selector) { + // 匹配校验 + if (this.annotationFilter.matches(annotationType)) { + return MergedAnnotation.missing(); + } + MergedAnnotation result = scan(annotationType, + new MergedAnnotationFinder<>(annotationType, predicate, selector)); + return (result != null ? result : MergedAnnotation.missing()); +} +``` + + + + + +#### Scan + +`org.springframework.core.annotation.AnnotationsScanner#scan(C, java.lang.reflect.AnnotatedElement, org.springframework.core.annotation.MergedAnnotations.SearchStrategy, org.springframework.core.annotation.AnnotationsProcessor, java.util.function.BiPredicate>)` + +```java +@Nullable +static R scan(C context, AnnotatedElement source, SearchStrategy searchStrategy, + AnnotationsProcessor processor, @Nullable BiPredicate> classFilter) { + + R result = process(context, source, searchStrategy, processor, classFilter); + return processor.finish(result); +} +``` + + + +在这个里面重点关注`PROCESS`方法 + +```java +@Nullable +private static R process(C context, AnnotatedElement source, + SearchStrategy searchStrategy, AnnotationsProcessor processor, + @Nullable BiPredicate> classFilter) { + + if (source instanceof Class) { + return processClass(context, (Class) source, searchStrategy, processor, classFilter); + } + if (source instanceof Method) { + return processMethod(context, (Method) source, searchStrategy, processor, classFilter); + } + return processElement(context, source, processor, classFilter); +} +``` + + + +测试类 + +```java + @Transactional("TxConfig") + static class TxConfig { + } +``` + +显然这是一个类他会走`processClass`方法 + + + +- 根据扫描方式进行扫描 + +```java +@Nullable +private static R processClass(C context, Class source, + SearchStrategy searchStrategy, AnnotationsProcessor processor, + @Nullable BiPredicate> classFilter) { + + switch (searchStrategy) { + case DIRECT: + return processElement(context, source, processor, classFilter); + case INHERITED_ANNOTATIONS: + return processClassInheritedAnnotations(context, source, searchStrategy, processor, classFilter); + case SUPERCLASS: + return processClassHierarchy(context, source, processor, classFilter, false, false); + case TYPE_HIERARCHY: + return processClassHierarchy(context, source, processor, classFilter, true, false); + case TYPE_HIERARCHY_AND_ENCLOSING_CLASSES: + return processClassHierarchy(context, source, processor, classFilter, true, true); + } + throw new IllegalStateException("Unsupported search strategy " + searchStrategy); +} +``` + + + +- 扫描的形式就不贴出完整代码了 + + + +`finish`就包装一下返回. + +- 此时`org.springframework.core.annotation.AnnotatedElementUtils#getMergedAnnotationAttributes(java.lang.reflect.AnnotatedElement, java.lang.String, boolean, boolean)`这个方法走到了最后一步`org.springframework.core.annotation.AnnotatedElementUtils#getAnnotationAttributes` + + + + + +- 最后的组装map方法 + + `org.springframework.core.annotation.TypeMappedAnnotation#asMap(java.util.function.Function,T>, org.springframework.core.annotation.MergedAnnotation.Adapt...)` + + + + + +```java +@Override +public AnnotationAttributes asAnnotationAttributes(Adapt... adaptations) { + return asMap(mergedAnnotation -> new AnnotationAttributes(mergedAnnotation.getType()), adaptations); +} +``` + + + +```java +@Override +public > T asMap(Function, T> factory, Adapt... adaptations) { + T map = factory.apply(this); + Assert.state(map != null, "Factory used to create MergedAnnotation Map must not return null"); + AttributeMethods attributes = this.mapping.getAttributes(); + for (int i = 0; i < attributes.size(); i++) { + Method attribute = attributes.get(i); + Object value = (isFiltered(attribute.getName()) ? null : + getValue(i, getTypeForMapOptions(attribute, adaptations))); + if (value != null) { + map.put(attribute.getName(), + adaptValueForMapOptions(attribute, value, map.getClass(), factory, adaptations)); + } + } + return map; +} +``` + +- 获取属性列表,循环, 放入map 返回. + + map + + ​ key: 注解的函数 + + ​ value: 函数对应的值 + + + +```java +@Transactional("TxConfig") +``` + +```java +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +@Inherited +@interface Transactional { + + String value() default ""; + + String qualifier() default "transactionManager"; + + boolean readOnly() default false; +} +``` + +如果是上面这样的结构那么返回值为 + +```json +value:TxConfig +qulifiter:transactionManager +readOnlay:false +``` + +![image-20200824104529315](/images/spring/image-20200824104529315.png) + + + + + + + + + + + +## SimpleMetadataReader + +- 构造方法传递三个参数直接使用 + + ```java + final class SimpleMetadataReader implements MetadataReader { + + private static final int PARSING_OPTIONS = ClassReader.SKIP_DEBUG + | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES; + + private final Resource resource; + + private final AnnotationMetadata annotationMetadata; + + + SimpleMetadataReader(Resource resource, @Nullable ClassLoader classLoader) throws IOException { + SimpleAnnotationMetadataReadingVisitor visitor = new SimpleAnnotationMetadataReadingVisitor(classLoader); + getClassReader(resource).accept(visitor, PARSING_OPTIONS); + this.resource = resource; + this.annotationMetadata = visitor.getMetadata(); + } + + private static ClassReader getClassReader(Resource resource) throws IOException { + try (InputStream is = new BufferedInputStream(resource.getInputStream())) { + try { + return new ClassReader(is); + } + catch (IllegalArgumentException ex) { + throw new NestedIOException("ASM ClassReader failed to parse class file - " + + "probably due to a new Java class file version that isn't supported yet: " + resource, ex); + } + } + } + + + @Override + public Resource getResource() { + return this.resource; + } + + @Override + public ClassMetadata getClassMetadata() { + return this.annotationMetadata; + } + + @Override + public AnnotationMetadata getAnnotationMetadata() { + return this.annotationMetadata; + } + + } + ``` + + + + + + + +## SimpleMetadataReaderFactory + +- 关注点为如何获取`MetadataReader` + 1. 通过资源直接new出来 + 2. 通过className转换成资源地址, + 3. 将资源地址转换成`Resource`对象 + 4. new出来 + +```java +@Override +public MetadataReader getMetadataReader(String className) throws IOException { + try { + String resourcePath = ResourceLoader.CLASSPATH_URL_PREFIX + + ClassUtils.convertClassNameToResourcePath(className) + ClassUtils.CLASS_FILE_SUFFIX; + Resource resource = this.resourceLoader.getResource(resourcePath); + return getMetadataReader(resource); + } + catch (FileNotFoundException ex) { + // Maybe an inner class name using the dot name syntax? Need to use the dollar syntax here... + // ClassUtils.forName has an equivalent check for resolution into Class references later on. + int lastDotIndex = className.lastIndexOf('.'); + if (lastDotIndex != -1) { + String innerClassName = + className.substring(0, lastDotIndex) + '$' + className.substring(lastDotIndex + 1); + String innerClassResourcePath = ResourceLoader.CLASSPATH_URL_PREFIX + + ClassUtils.convertClassNameToResourcePath(innerClassName) + ClassUtils.CLASS_FILE_SUFFIX; + Resource innerClassResource = this.resourceLoader.getResource(innerClassResourcePath); + if (innerClassResource.exists()) { + return getMetadataReader(innerClassResource); + } + } + throw ex; + } +} + +@Override +public MetadataReader getMetadataReader(Resource resource) throws IOException { + return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader()); +} +``` \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-SpringFactoriesLoader.md b/docs/Spring/clazz/Spring-SpringFactoriesLoader.md new file mode 100644 index 0000000..28890a0 --- /dev/null +++ b/docs/Spring/clazz/Spring-SpringFactoriesLoader.md @@ -0,0 +1,139 @@ +# SpringFactoriesLoader +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring-boot](https://github.com/SourceHot/spring-boot-read) + + +- 全路径 : `org.springframework.core.io.support.SpringFactoriesLoader` +- 测试类 : `org.springframework.core.io.support.SpringFactoriesLoaderTests` + + +## loadFactories + +- **加载并实例化工厂** + +```java +public static List loadFactories(Class factoryType, @Nullable ClassLoader classLoader) { + Assert.notNull(factoryType, "'factoryType' must not be null"); + ClassLoader classLoaderToUse = classLoader; + if (classLoaderToUse == null) { + classLoaderToUse = SpringFactoriesLoader.class.getClassLoader(); + } + // 工厂实现类名称 + List factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse); + if (logger.isTraceEnabled()) { + logger.trace("Loaded [" + factoryType.getName() + "] names: " + factoryImplementationNames); + } + List result = new ArrayList<>(factoryImplementationNames.size()); + for (String factoryImplementationName : factoryImplementationNames) { + // 将实例化的工厂放入结果集合 + result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse)); + } + // 排序 + AnnotationAwareOrderComparator.sort(result); + return result; + } +``` + + + + + +## loadSpringFactories + +- 获取接口的实现类名 + +```java + private static Map> loadSpringFactories(@Nullable ClassLoader classLoader) { + MultiValueMap result = cache.get(classLoader); + if (result != null) { + return result; + } + + try { + // 找 META-INF/spring.factories + Enumeration urls = (classLoader != null ? + classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : + ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); + result = new LinkedMultiValueMap<>(); + while (urls.hasMoreElements()) { + // 获取 路由地址 + URL url = urls.nextElement(); + // url 解析 + UrlResource resource = new UrlResource(url); + // Properties 解析 + Properties properties = PropertiesLoaderUtils.loadProperties(resource); + // 循环解析结果 + for (Map.Entry entry : properties.entrySet()) { + String factoryTypeName = ((String) entry.getKey()).trim(); + for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) { + // 放入list + result.add(factoryTypeName, factoryImplementationName.trim()); + } + } + } + // 放入缓存 + cache.put(classLoader, result); + return result; + } + catch (IOException ex) { + throw new IllegalArgumentException("Unable to load factories from location [" + + FACTORIES_RESOURCE_LOCATION + "]", ex); + } + } + +``` + +- 存放在 测试目录下的`META-INF/spring.factories` + + ```properties + org.springframework.core.io.support.DummyFactory =\ + org.springframework.core.io.support.MyDummyFactory2, \ + org.springframework.core.io.support.MyDummyFactory1 + + java.lang.String=\ + org.springframework.core.io.support.MyDummyFactory1 + + org.springframework.core.io.support.DummyPackagePrivateFactory=\ + org.springframework.core.io.support.DummyPackagePrivateFactory + + ``` + + + +- `Enumeration urls ` 变量存放的是 扫描到的`META-INF/spring.factories` 路径 + +- while 代码简单描述 + 1. 获取文件路径 + 2. 文件路径解析 + 3. 读取文件 Properties 解析 + 4. 放入返回结果 + 5. 放入缓存 + + + +## instantiateFactory + +```java +@SuppressWarnings("unchecked") +private static T instantiateFactory(String factoryImplementationName, Class factoryType, ClassLoader classLoader) { + try { + Class factoryImplementationClass = ClassUtils.forName(factoryImplementationName, classLoader); + if (!factoryType.isAssignableFrom(factoryImplementationClass)) { + throw new IllegalArgumentException( + "Class [" + factoryImplementationName + "] is not assignable to factory type [" + factoryType.getName() + "]"); + } + return (T) ReflectionUtils.accessibleConstructor(factoryImplementationClass).newInstance(); + } + catch (Throwable ex) { + throw new IllegalArgumentException( + "Unable to instantiate factory class [" + factoryImplementationName + "] for factory type [" + factoryType.getName() + "]", + ex + ); + } +} +``` + +- 反射创建 + + + diff --git a/docs/Spring/clazz/Spring-beanFactory.md b/docs/Spring/clazz/Spring-beanFactory.md new file mode 100644 index 0000000..77a4f07 --- /dev/null +++ b/docs/Spring/clazz/Spring-beanFactory.md @@ -0,0 +1,3152 @@ +# Spring BeanFactory +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read) + +## BeanFactory 概述 +- `org.springframework.beans.factory.BeanFactory` + +### 类图 + +![beanFactory](/images/spring/BeanFactory.png) + + + +### 方法列表 +- 贴出部分代码. 仅表示方法作用 +```java +public interface BeanFactory { + // 从容器中根据beanname获取 + Object getBean(String name) throws BeansException; + // 延迟加载对象 + ObjectProvider getBeanProvider(Class requiredType); + // 是否存在beanName + boolean containsBean(String name); + // 这个 beanName 是否是单例的. 映射成 bean + boolean isSingleton(String name) throws NoSuchBeanDefinitionException; + // 是否多例. + boolean isPrototype(String name) throws NoSuchBeanDefinitionException; + // 类型是否匹配 + boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException; + // 获取bean的类型 + Class getType(String name) throws NoSuchBeanDefinitionException; + // 获取别名 + String[] getAliases(String name); +} +``` + + + +## 解析 + +### 用例 + +bean 的实例化有如下几种方法 + +1. 静态方法 +2. 工厂方法创建 +3. FactoryBean 接口创建 + + + + + +### 代码部分 + +```java +public class UserBean { + + private String name; + private Integer age; + + public static UserBean createInstance() { + UserBean userBean = new UserBean(); + userBean.setAge(18); + userBean.setName("zhangsan"); + + return userBean; + } + // get set 忽略 +} +``` + + + +```java +public interface UserBeanFactory { + UserBean factory(); +} + +public class UserBeanFactoryImpl implements + UserBeanFactory { + + + @Override + public UserBean factory() { + return UserBean.createInstance(); + } +} + +``` + + + + + +```java +public class UserFactoryBean implements FactoryBean { + + @Override + public boolean isSingleton() { + return true; + } + + @Override + public UserBean getObject() throws Exception { + return UserBean.createInstance(); + } + + @Override + public Class getObjectType() { + return UserBean.class; + } +} +``` + +```xml + + + + + + + + + + + + + + + +``` + + + +```java +public class SpringBeanInstantiation { + + public static void main(String[] args) { + BeanFactory context = new ClassPathXmlApplicationContext( + "META-INF/beans/spring-bean-instantiation.xml"); + + UserBean staticMethodBean = context.getBean("static-method-user", UserBean.class); + UserBean factoryUser = context.getBean("factory-use", UserBean.class); + UserBean factoryBean = context.getBean("factory-bean-user", UserBean.class); + System.out.println(); + + } +} +``` + + + + + +### 分析 + +- 对下面代码进行分析 + +```java + UserBean staticMethodBean = context.getBean("static-method-user", UserBean.class); +``` + + + +- `org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.String, java.lang.Class)` + +```java +@Override + public T getBean(String name, Class requiredType) throws BeansException { + // 判断 beanFactory 是否存活 + assertBeanFactoryActive(); + + // 1. 获取 beanFactory + // 2. 根据 beanName + class 获取 Bean + return getBeanFactory().getBean(name, requiredType); + } +``` + +- 从方法参数 + - name: beanName + - requiredType: 唯一的类型. 对象类型 + + + + + +### assertBeanFactoryActive + +- beanFactory 是否存活判断 + +```java +protected void assertBeanFactoryActive() { + // 是否存活 + if (!this.active.get()) { + // 是否关闭 + if (this.closed.get()) { + throw new IllegalStateException(getDisplayName() + " has been closed already"); + } + else { + throw new IllegalStateException(getDisplayName() + " has not been refreshed yet"); + } + } + } +``` + + + +### getBeanFactory + +- 获取beanFactory + + - 获取方法是一个抽象方法 + + ```java + public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException; + ``` + + - 子类实现 + + `org.springframework.context.support.AbstractRefreshableApplicationContext#getBeanFactory` + + ```java + @Override + public final ConfigurableListableBeanFactory getBeanFactory() { + synchronized (this.beanFactoryMonitor) { + if (this.beanFactory == null) { + throw new IllegalStateException("BeanFactory not initialized or already closed - " + + "call 'refresh' before accessing beans via the ApplicationContext"); + } + return this.beanFactory; + } + } + ``` + + - `org.springframework.context.support.GenericApplicationContext#getBeanFactory` + + ```java + @Override + public final ConfigurableListableBeanFactory getBeanFactory() { + return this.beanFactory; + } + ``` + + + +- 获取到的对象是`org.springframework.beans.factory.support.DefaultListableBeanFactory` + + + +![image-20200902102912716](images/image-20200902102912716.png) + +- 整体类图 + +![image-20200902103154580](images/image-20200902103154580.png) + + + + + +### doGetBean + +- `org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean` + + 获取 bean 的核心 + + + + + + + +#### transformedBeanName + +```java +protected String transformedBeanName(String name) { + // 转换 beanName . + // 1. 通过·BeanFactoryUtils.transformedBeanName· 求beanName + // 2. 如果是有别名的(方法参数是别名) . 会从别名列表中获取对应的 beanName + return canonicalName(BeanFactoryUtils.transformedBeanName(name)); +} +``` + + + +```java +public static String transformedBeanName(String name) { + Assert.notNull(name, "'name' must not be null"); + // 名字不是 & 开头直接返回 + if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) { + return name; + } + // 截取字符串 在返回 + return transformedBeanNameCache.computeIfAbsent(name, beanName -> { + do { + beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length()); + } + while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)); + return beanName; + }); +} +``` + +```java +public String canonicalName(String name) { + String canonicalName = name; + // Handle aliasing... + String resolvedName; + do { + // 别名的获取 + resolvedName = this.aliasMap.get(canonicalName); + if (resolvedName != null) { + canonicalName = resolvedName; + } + } + while (resolvedName != null); + return canonicalName; +} +``` + +别名对象 + +```java +private final Map aliasMap = new ConcurrentHashMap<>(16); +``` + +```java + + + +``` + +aliasMap 和 别名标签的对应关系 + +![image-20200902105454958](images/image-20200902105454958.png) + + + +alias标签的alias值作为别名的key , alias 标签的 name 值作为 value + + + + + +#### getSingleton + +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)` + + + +```java +@Override +@Nullable +public Object getSingleton(String beanName) { + return getSingleton(beanName, true); +} +``` + + + +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)` + + + +```java +@Nullable +protected Object getSingleton(String beanName, boolean allowEarlyReference) { + // 尝试从单例缓存中获取 + Object singletonObject = this.singletonObjects.get(beanName); + // 单例对象是否null + // 这个 beanName 是否正在创建 + if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { + // 锁 + synchronized (this.singletonObjects) { + // 从延迟加载的map中获取 + singletonObject = this.earlySingletonObjects.get(beanName); + // 对象是否空 , 是否允许提前应用 + if (singletonObject == null && allowEarlyReference) { + // 从对象工厂map中获取对象工厂 + ObjectFactory singletonFactory = this.singletonFactories.get(beanName); + if (singletonFactory != null) { + // 对象获取后设置 + singletonObject = singletonFactory.getObject(); + this.earlySingletonObjects.put(beanName, singletonObject); + this.singletonFactories.remove(beanName); + } + } + } + } + return singletonObject; +} +``` + +- 相关属性值 + + + +```java +/** + * Cache of singleton objects: bean name to bean instance. + * + * 单例对象容器, key: beanName , value: bean实例 + * */ +private final Map singletonObjects = new ConcurrentHashMap<>(256); + + + /** + * Cache of singleton factories: bean name to ObjectFactory. + * key: beanName + * value: 对象工厂 + * */ + private final Map> singletonFactories = new HashMap<>(16); + + + + /** + * Names of beans that are currently in creation. + * + * 当前正在实例化的beanName + * + * */ + private final Set singletonsCurrentlyInCreation = + Collections.newSetFromMap(new ConcurrentHashMap<>(16)); +``` + + + + + + + +#### getObjectForBeanInstance + +- `org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance` + + + +```java +protected Object getObjectForBeanInstance( + Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { + + // Don't let calling code try to dereference the factory if the bean isn't a factory. + // 判断 beanName 是不是 bean 工厂 + if (BeanFactoryUtils.isFactoryDereference(name)) { + // 类型判断 + if (beanInstance instanceof NullBean) { + return beanInstance; + } + if (!(beanInstance instanceof FactoryBean)) { + throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass()); + } + if (mbd != null) { + mbd.isFactoryBean = true; + } + // 返回实例 + return beanInstance; + } + + // Now we have the bean instance, which may be a normal bean or a FactoryBean. + // If it's a FactoryBean, we use it to create a bean instance, unless the + // caller actually wants a reference to the factory. + // 判断是否是 factoryBean + if (!(beanInstance instanceof FactoryBean)) { + return beanInstance; + } + + Object object = null; + if (mbd != null) { + mbd.isFactoryBean = true; + } + else { + // 缓存中获取 + object = getCachedObjectForFactoryBean(beanName); + } + if (object == null) { + // Return bean instance from factory. + // 如果还是 null 从 factory bean 中创建 + FactoryBean factory = (FactoryBean) beanInstance; + // Caches object obtained from FactoryBean if it is a singleton. + if (mbd == null && containsBeanDefinition(beanName)) { + mbd = getMergedLocalBeanDefinition(beanName); + } + boolean synthetic = (mbd != null && mbd.isSynthetic()); + // 从 FactoryBean 中获取bean实例 + object = getObjectFromFactoryBean(factory, beanName, !synthetic); + } + return object; + } +``` + + + + + +#### getObjectFromFactoryBean + +- `org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean` + +- 从 FactoryBean 中获取对象 + +```java + protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) { + // 是否单例 是否已经包含 + if (factory.isSingleton() && containsSingleton(beanName)) { + synchronized (getSingletonMutex()) { + // 从工厂bean的缓存中获取 + Object object = this.factoryBeanObjectCache.get(beanName); + if (object == null) { + + // 从 factoryBean 接口中获取 + object = doGetObjectFromFactoryBean(factory, beanName); + // Only post-process and store if not put there already during getObject() call above + // (e.g. because of circular reference processing triggered by custom getBean calls) + // 从缓存map中获取 + Object alreadyThere = this.factoryBeanObjectCache.get(beanName); + if (alreadyThere != null) { + // 如果缓存中获取有值 + // object 覆盖 + object = alreadyThere; + } + else { + if (shouldPostProcess) { + if (isSingletonCurrentlyInCreation(beanName)) { + // Temporarily return non-post-processed object, not storing it yet.. + return object; + } + // 单例创建前的验证 + beforeSingletonCreation(beanName); + try { + // 从 FactoryBean 接口创建的 后置处理 + object = postProcessObjectFromFactoryBean(object, beanName); + } + catch (Throwable ex) { + throw new BeanCreationException(beanName, + "Post-processing of FactoryBean's singleton object failed", ex); + } + finally { + // 单例bean创建之后 + afterSingletonCreation(beanName); + } + } + // 是否包含bean name + if (containsSingleton(beanName)) { + // 插入缓存 + // 后续使用的时候可以直接获取 + this.factoryBeanObjectCache.put(beanName, object); + } + } + } + return object; + } + } + else { + Object object = doGetObjectFromFactoryBean(factory, beanName); + if (shouldPostProcess) { + try { + object = postProcessObjectFromFactoryBean(object, beanName); + } + catch (Throwable ex) { + throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex); + } + } + return object; + } + } + +``` + + + + + +#### beforeSingletonCreation + +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#beforeSingletonCreation` + +- 单例创建前的验证 + +```java +protected void beforeSingletonCreation(String beanName) { + // 排除的单例beanName 是否包含当前beanName + // 添加当前正在初始化的beanName 是否正确 + if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { + throw new BeanCurrentlyInCreationException(beanName); + } +} +``` + + + +#### postProcessObjectFromFactoryBean + +- 两种实现 + + - `org.springframework.beans.factory.support.FactoryBeanRegistrySupport#postProcessObjectFromFactoryBean` + + ```JAVA + protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException { + return object; + } + ``` + + 直接返回 object + + - `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#postProcessObjectFromFactoryBean` 调用 `BeanPostProcessor` + + ```java + @Override + protected Object postProcessObjectFromFactoryBean(Object object, String beanName) { + return applyBeanPostProcessorsAfterInitialization(object, beanName); + } + + + @Override + public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) + throws BeansException { + + Object result = existingBean; + for (BeanPostProcessor processor : getBeanPostProcessors()) { + Object current = processor.postProcessAfterInitialization(result, beanName); + if (current == null) { + return result; + } + result = current; + } + return result; + } + + ``` + +- 两个方法军返回 `Bean` 对象 . 一种是直接返回 。 另一种是执行接口 `BeanPostProcessor` 接口返回 + + + + + +#### afterSingletonCreation + +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#afterSingletonCreation` + +```java +protected void afterSingletonCreation(String beanName) { + // 排除的单例beanName 是否包含当前beanName + // 移除当前正在初始化的beanName 是否正确 + if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) { + throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation"); + } +} +``` + + + + + + + +- 代码现在进入的很深了,回到 doGetBean +- `org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean` + +```JAVA + protected T doGetBean(final String name, @Nullable final Class requiredType, + @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { + // 转换beanName + final String beanName = transformedBeanName(name); + Object bean; + + // Eagerly check singleton cache for manually registered singletons. + // 获取单例对象 + Object sharedInstance = getSingleton(beanName); + // 单例对象是否存在 参数是否为空 + if (sharedInstance != null && args == null) { + if (logger.isTraceEnabled()) { + if (isSingletonCurrentlyInCreation(beanName)) { + logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + + "' that is not fully initialized yet - a consequence of a circular reference"); + } + else { + logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); + } + } + // 实例化bean + bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); + } + + // 省略后续内容 + } +``` + + + +- 目前未知`doGetBean`的第一个`if`分支已经分析完毕. 接下来看下面的代码 + + + +- 下面这段代码就简单说一下就跳过了。 + - 从 容器中获取,最后还是回到doGetBean方法中. 来进行bean创建 这里不进行展开。 + +```java +else { + // Fail if we're already creating this bean instance: + // We're assumably within a circular reference. + // 循环依赖的问题 + if (isPrototypeCurrentlyInCreation(beanName)) { + throw new BeanCurrentlyInCreationException(beanName); + } + + // Check if bean definition exists in this factory. + BeanFactory parentBeanFactory = getParentBeanFactory(); + if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { + // Not found -> check parent. + String nameToLookup = originalBeanName(name); + if (parentBeanFactory instanceof AbstractBeanFactory) { + return ((AbstractBeanFactory) parentBeanFactory).doGetBean( + nameToLookup, requiredType, args, typeCheckOnly); + } + else if (args != null) { + // Delegation to parent with explicit args. + return (T) parentBeanFactory.getBean(nameToLookup, args); + } + else if (requiredType != null) { + // No args -> delegate to standard getBean method. + return parentBeanFactory.getBean(nameToLookup, requiredType); + } + else { + return (T) parentBeanFactory.getBean(nameToLookup); + } + } +``` + + + + + +#### markBeanAsCreated + +- `org.springframework.beans.factory.support.AbstractBeanFactory#markBeanAsCreated` + +- 方法作用将bean标记为已创建 + + + +``` +protected void markBeanAsCreated(String beanName) { + // 已创建的beanName 是否包含当前beanName + if (!this.alreadyCreated.contains(beanName)) { + synchronized (this.mergedBeanDefinitions) { + if (!this.alreadyCreated.contains(beanName)) { + // Let the bean definition get re-merged now that we're actually creating + // the bean... just in case some of its metadata changed in the meantime. + // 将属性stale设置true + clearMergedBeanDefinition(beanName); + // 放入已创建集合中 + this.alreadyCreated.add(beanName); + } + } + } +} +``` + + + + + +```java +protected void clearMergedBeanDefinition(String beanName) { + RootBeanDefinition bd = this.mergedBeanDefinitions.get(beanName); + if (bd != null) { + bd.stale = true; + } +} +``` + + + +- stale 的解释 + + ```java + /** + * Determines if the definition needs to be re-merged. + * 是否需要重新合并定义 + * */ + volatile boolean stale; + ``` + +- 属性值 已创建的beanName + + ```java + private final Set alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256)); + ``` + + + + + + + +#### getMergedLocalBeanDefinition + +- `org.springframework.beans.factory.support.AbstractBeanFactory#getMergedLocalBeanDefinition` + +- 这个方法获取一个`RootBeanDefinition`对象 , 这个对象也是bean的一种定义。 +- 从目前的几个方法名称来看,暂且认为这是一个合并了多个 `BeanDefinition`的对象吧 + +![rootBeanDefinition](/images/spring/RootBeanDefinition.png) + + + + + +```java +protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException { + // Quick check on the concurrent map first, with minimal locking. + // 缓存中获取 + RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName); + if (mbd != null && !mbd.stale) { + return mbd; + } + // 合并的 bean 定义 + return getMergedBeanDefinition(beanName, getBeanDefinition(beanName)); +} + + + protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd) + throws BeanDefinitionStoreException { + + return getMergedBeanDefinition(beanName, bd, null); + } + +``` + + + + + +#### getBeanDefinition + +- 获取 `beanDefinition ` +- `org.springframework.beans.factory.support.DefaultListableBeanFactory#getBeanDefinition` + +```java +@Override +public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { + BeanDefinition bd = this.beanDefinitionMap.get(beanName); + if (bd == null) { + if (logger.isTraceEnabled()) { + logger.trace("No bean named '" + beanName + "' found in " + this); + } + throw new NoSuchBeanDefinitionException(beanName); + } + return bd; +} +``` + +- 从 beanDefinition map 中获取 + +- 相关属性 + + ```java + /** + * Map of bean definition objects, keyed by bean name. + * + * key: beanName + * value: BeanDefinition + * + * */ + private final Map beanDefinitionMap = new ConcurrentHashMap<>(256); + ``` + + + + + +#### getMergedBeanDefinition + +- 获取`RootBeanDefinition` + +- `org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition(java.lang.String, org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.config.BeanDefinition)` + +- 第一部分代码 + - map 中获取 RootBeanDefinition + - 是否存在父名称 + - 类型是否是 `RootBeanDefinition` + - 是: 拷贝 + - 否: 将 `BeanDefinition` 转换成 `RootBeanDefinition` + +```java +protected RootBeanDefinition getMergedBeanDefinition( + String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd) + throws BeanDefinitionStoreException { + + synchronized (this.mergedBeanDefinitions) { + RootBeanDefinition mbd = null; + RootBeanDefinition previous = null; + + // Check with full lock now in order to enforce the same merged instance. + if (containingBd == null) { + // 从缓存中获取 + mbd = this.mergedBeanDefinitions.get(beanName); + } + + if (mbd == null || mbd.stale) { + previous = mbd; + // 是否存在父名称 + if (bd.getParentName() == null) { + // Use copy of given root bean definition. + // 类型是否等于RootBeanDefinition + if (bd instanceof RootBeanDefinition) { + // 做一次对象拷贝 + mbd = ((RootBeanDefinition) bd).cloneBeanDefinition(); + } + else { + // 将 beanDefinition 创建成 RootBeanDefinition + mbd = new RootBeanDefinition(bd); + } + } + + // 省略其他 + } +``` + +- 相关属性 + + ```java + /** + * Map from bean name to merged RootBeanDefinition. + * key: beanName + * value: RootBeanDefinition + * */ + private final Map mergedBeanDefinitions = new ConcurrentHashMap<>(256); + ``` + +- 克隆 方法 + + ```java + /** + * 克隆 BeanDefinition + * @return + */ + @Override + public RootBeanDefinition cloneBeanDefinition() { + return new RootBeanDefinition(this); + } + ``` + + + + + +- 第二部分代码 + + + + + + + +```java +{ + // Child bean definition: needs to be merged with parent. + // 父BeanDefinition + BeanDefinition pbd; + try { + // 父类beanName + String parentBeanName = transformedBeanName(bd.getParentName()); + // 当前beanName是否等于父的beanName + if (!beanName.equals(parentBeanName)) { + // 存在父 beanName + // 父 beanDefinition + // 递归调用 + pbd = getMergedBeanDefinition(parentBeanName); + } + else { + // 获取父 beanFactory + BeanFactory parent = getParentBeanFactory(); + // beanFactory 类型判断 + if (parent instanceof ConfigurableBeanFactory) { + // ConfigurableBeanFactory 的获取方式 + pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName); + } + else { + throw new NoSuchBeanDefinitionException(parentBeanName, + "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName + + "': cannot be resolved without an AbstractBeanFactory parent"); + } + } + } + catch (NoSuchBeanDefinitionException ex) { + throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName, + "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex); + } + // Deep copy with overridden values. + // 将 父 BeanDefinition 对象拷贝 + mbd = new RootBeanDefinition(pbd); + // 覆盖 beanDefinition + mbd.overrideFrom(bd); + } +``` + + + +#### overrideFrom + +- 覆盖方法 + +- `org.springframework.beans.factory.support.AbstractBeanDefinition#overrideFrom` + + + +- 最后一段 + + + + + +```java + // Set default singleton scope, if not configured before. + // 作用域设置 + if (!StringUtils.hasLength(mbd.getScope())) { + // 没有设置作用域直接给单例类型 + mbd.setScope(SCOPE_SINGLETON); + } + + // A bean contained in a non-singleton bean cannot be a singleton itself. + // Let's correct this on the fly here, since this might be the result of + // parent-child merging for the outer bean, in which case the original inner bean + // definition will not have inherited the merged outer bean's singleton status. + // 修正 作用域 + if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) { + mbd.setScope(containingBd.getScope()); + } + + // Cache the merged bean definition for the time being + // (it might still get re-merged later on in order to pick up metadata changes) + if (containingBd == null && isCacheBeanMetadata()) { + // 放入缓存 + this.mergedBeanDefinitions.put(beanName, mbd); + } +} +if (previous != null) { + copyRelevantMergedBeanDefinitionCaches(previous, mbd); +} +return mbd; +``` + + + + + + + + + +#### checkMergedBeanDefinition + +- `org.springframework.beans.factory.support.AbstractBeanFactory#checkMergedBeanDefinition` + + ```java + protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args) + throws BeanDefinitionStoreException { + + if (mbd.isAbstract()) { + throw new BeanIsAbstractException(beanName); + } + } + ``` + + - 判断是否 abstract 标记的情况 + + + + + + + +- 继续回到 `doGetBean` 方法 + +```java +// 需要依赖的bean +String[] dependsOn = mbd.getDependsOn(); +if (dependsOn != null) { + for (String dep : dependsOn) { + if (isDependent(beanName, dep)) { + throw new BeanCreationException(mbd.getResourceDescription(), beanName, + "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); + } + // 注册依赖bean + registerDependentBean(dep, beanName); + try { + getBean(dep); + } + catch (NoSuchBeanDefinitionException ex) { + throw new BeanCreationException(mbd.getResourceDescription(), beanName, + "'" + beanName + "' depends on missing bean '" + dep + "'", ex); + } + } +} +``` + + + + + + +#### isDependent + +- 是否存在依赖关系 + +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#isDependent(java.lang.String, java.lang.String, java.util.Set)` + +```java +private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set alreadySeen) { + if (alreadySeen != null && alreadySeen.contains(beanName)) { + return false; + } + // 别名 + String canonicalName = canonicalName(beanName); + // 依赖列表中获取 + Set dependentBeans = this.dependentBeanMap.get(canonicalName); + if (dependentBeans == null) { + return false; + } + if (dependentBeans.contains(dependentBeanName)) { + return true; + } + for (String transitiveDependency : dependentBeans) { + if (alreadySeen == null) { + alreadySeen = new HashSet<>(); + } + alreadySeen.add(beanName); + if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) { + return true; + } + } + return false; +} +``` + + + +- 相关属性 + + ```java + /** + * Map between dependent bean names: bean name to Set of dependent bean names. + * + * key: bean + * value: 依赖列表 + * */ + private final Map> dependentBeanMap = new ConcurrentHashMap<>(64); + ``` + + + + + +- 一个用例 + +```xml + + + +``` + + + +![image-20200903091759451](images/image-20200903091759451.png) + + + + + + + +#### registerDependentBean + +- 注册依赖关系 +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#registerDependentBean` + - 在前文调用 `isDependent` 方法的的时候我们找到了一个依赖映射`dependentBeanMap` ,在这个方法中会将依赖关系放入`dependentBeanMap` + + + + + +```java +public void registerDependentBean(String beanName, String dependentBeanName) { + // 别名 + String canonicalName = canonicalName(beanName); + + synchronized (this.dependentBeanMap) { + // 向依赖关系中放入数据 + Set dependentBeans = + this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8)); + if (!dependentBeans.add(dependentBeanName)) { + return; + } + } + + synchronized (this.dependenciesForBeanMap) { + Set dependenciesForBean = + this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8)); + dependenciesForBean.add(canonicalName); + } +} +``` + + + + + +- 再回到 `doGetBean` + +- 接下来就是实例化的过程了. + +```java +if (mbd.isSingleton()) { + sharedInstance = getSingleton(beanName, () -> { + try { + return createBean(beanName, mbd, args); + } + catch (BeansException ex) { + // Explicitly remove instance from singleton cache: It might have been put there + // eagerly by the creation process, to allow for circular reference resolution. + // Also remove any beans that received a temporary reference to the bean. + destroySingleton(beanName); + throw ex; + } + }); + bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); +} +``` + + + + + +#### getSingleton + +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory)` +- 获取单例对象 + 1. 从单例对象的map缓存中获取 + 2. 从 ObjectFactory 中获取 + +- 周边方法 + + - `beforeSingletonCreation` + + - `afterSingletonCreation` + - `addSingleton` + +```java +public Object getSingleton(String beanName, ObjectFactory singletonFactory) { + Assert.notNull(beanName, "Bean name must not be null"); + synchronized (this.singletonObjects) { + // 从单例对象缓存中获取 + Object singletonObject = this.singletonObjects.get(beanName); + if (singletonObject == null) { + if (this.singletonsCurrentlyInDestruction) { + throw new BeanCreationNotAllowedException(beanName, + "Singleton bean creation not allowed while singletons of this factory are in destruction " + + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); + } + if (logger.isDebugEnabled()) { + logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); + } + // 单例创建前的验证 + beforeSingletonCreation(beanName); + boolean newSingleton = false; + boolean recordSuppressedExceptions = (this.suppressedExceptions == null); + if (recordSuppressedExceptions) { + this.suppressedExceptions = new LinkedHashSet<>(); + } + try { + // 从 ObjectFactory 中获取 + singletonObject = singletonFactory.getObject(); + newSingleton = true; + } + catch (IllegalStateException ex) { + // Has the singleton object implicitly appeared in the meantime -> + // if yes, proceed with it since the exception indicates that state. + singletonObject = this.singletonObjects.get(beanName); + if (singletonObject == null) { + throw ex; + } + } + catch (BeanCreationException ex) { + if (recordSuppressedExceptions) { + for (Exception suppressedException : this.suppressedExceptions) { + ex.addRelatedCause(suppressedException); + } + } + throw ex; + } + finally { + if (recordSuppressedExceptions) { + this.suppressedExceptions = null; + } + // 创建单例对象后的验证 + afterSingletonCreation(beanName); + } + if (newSingleton) { + // 添加到 单例容器中 + addSingleton(beanName, singletonObject); + } + } + return singletonObject; + } +} +``` + + + + + +- 回到 doGetBean 方法中 + + ```java + if (mbd.isSingleton()) { + // 判断是否是单例 + sharedInstance = getSingleton(beanName, () -> { + try { + return createBean(beanName, mbd, args); + } + catch (BeansException ex) { + // Explicitly remove instance from singleton cache: It might have been put there + // eagerly by the creation process, to allow for circular reference resolution. + // Also remove any beans that received a temporary reference to the bean. + destroySingleton(beanName); + throw ex; + } + }); + bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); + } + ``` + + 这里又要给 `createBean`方法, 从 `getSingleton` 的参数看可以知道 ,第二个匿名函数是`ObjectFactory`接口实现. + + ```java + @FunctionalInterface + public interface ObjectFactory { + + /** + * Return an instance (possibly shared or independent) + * of the object managed by this factory. + * 获取对象 + * @return the resulting instance + * @throws BeansException in case of creation errors + */ + T getObject() throws BeansException; + + } + ``` + + - createBean 返回的就是单例bean对象的实例 + + + + + + + +##### createBean + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])` + + + +- 两个核心方法 + +```JAVA +// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. +Object bean = resolveBeforeInstantiation(beanName, mbdToUse); +Object beanInstance = doCreateBean(beanName, mbdToUse, args); +``` + + + + + + + +###### resolveBeforeInstantiation + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation` + +- 方法概述: + + 获取`BeanPostProcessor`接口的实现列表 + + - `applyBeanPostProcessorsBeforeInstantiation` 前置方法执行 + - `applyBeanPostProcessorsAfterInitialization`后置方法执行 + +```java +@Nullable +protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { + Object bean = null; + if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { + // Make sure bean class is actually resolved at this point. + if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { + Class targetType = determineTargetType(beanName, mbd); + if (targetType != null) { + /** + * 主要实现{@link org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(java.lang.Class, java.lang.String)} + */ + bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); + if (bean != null) { + bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); + } + } + } + mbd.beforeInstantiationResolved = (bean != null); + } + return bean; +} +``` + + + + + +###### doCreateBean + +- 创建 bean +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean` + + + + + +```java + // Instantiate the bean. + BeanWrapper instanceWrapper = null; + if (mbd.isSingleton()) { + // beanFactory 移除当前创建的beanName + instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); + } + // beanWrapper 是否存在 + if (instanceWrapper == null) { + // 创建 bean 实例 + instanceWrapper = createBeanInstance(beanName, mbd, args); + } +``` + + + + + + + +###### createBeanInstance + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance` +- 创建 bean 实例 + +```java +protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { + // Make sure bean class is actually resolved at this point. + // 获取 bean class + Class beanClass = resolveBeanClass(mbd, beanName); + + if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { + throw new BeanCreationException(mbd.getResourceDescription(), beanName, + "Bean class isn't public, and non-public access not allowed: " + beanClass.getName() + ); + } + + // 返回一个用来创建bean实例的回调接口 + // Supplier get 直接获取bean对象 + Supplier instanceSupplier = mbd.getInstanceSupplier(); + if (instanceSupplier != null) { + return obtainFromSupplier(instanceSupplier, beanName); + } + + if (mbd.getFactoryMethodName() != null) { + // 通过工厂方法创建 + return instantiateUsingFactoryMethod(beanName, mbd, args); + } + + // Shortcut when re-creating the same bean... + boolean resolved = false; + boolean autowireNecessary = false; + if (args == null) { + synchronized (mbd.constructorArgumentLock) { + if (mbd.resolvedConstructorOrFactoryMethod != null) { + resolved = true; + autowireNecessary = mbd.constructorArgumentsResolved; + } + } + } + if (resolved) { + if (autowireNecessary) { + // 自动构造 bean + return autowireConstructor(beanName, mbd, null, null); + } + else { + // 实例化bean + return instantiateBean(beanName, mbd); + } + } + + // Candidate constructors for autowiring? + Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); + if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || + mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { + return autowireConstructor(beanName, mbd, ctors, args); + } + + // Preferred constructors for default construction? + ctors = mbd.getPreferredConstructors(); + if (ctors != null) { + return autowireConstructor(beanName, mbd, ctors, null); + } + + // No special handling: simply use no-arg constructor. + return instantiateBean(beanName, mbd); +} +``` + + + + + + + +###### resolveBeanClass + +- `org.springframework.beans.factory.support.AbstractBeanFactory#resolveBeanClass` +- 获取bean 的class + + + + + +```java +@Nullable +protected Class resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class... typesToMatch) + throws CannotLoadBeanClassException { + + try { + // 是否包含 bean 类型 + if (mbd.hasBeanClass()) { + // 直接返回 + return mbd.getBeanClass(); + } + if (System.getSecurityManager() != null) { + return AccessController.doPrivileged((PrivilegedExceptionAction>) () -> + doResolveBeanClass(mbd, typesToMatch), getAccessControlContext()); + } + else { + // 从 bean definition 中获取 + return doResolveBeanClass(mbd, typesToMatch); + } + } + catch (PrivilegedActionException pae) { + ClassNotFoundException ex = (ClassNotFoundException) pae.getException(); + throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); + } + catch (ClassNotFoundException ex) { + throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); + } + catch (LinkageError err) { + throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err); + } +} +``` + + + + + +###### doResolveBeanClass + +- `org.springframework.beans.factory.support.AbstractBeanFactory#doResolveBeanClass` + +- 第一段 + + ```java + ClassLoader beanClassLoader = getBeanClassLoader(); + ClassLoader dynamicLoader = beanClassLoader; + boolean freshResolve = false; + + // 判断 typesToMatch 是否为空 + if (!ObjectUtils.isEmpty(typesToMatch)) { + // When just doing type checks (i.e. not creating an actual instance yet), + // use the specified temporary class loader (e.g. in a weaving scenario). + // 获取临时类加载器 + ClassLoader tempClassLoader = getTempClassLoader(); + if (tempClassLoader != null) { + dynamicLoader = tempClassLoader; + freshResolve = true; + // 类型比较 + if (tempClassLoader instanceof DecoratingClassLoader) { + DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader; + for (Class typeToMatch : typesToMatch) { + // 添加排除的类 + dcl.excludeClass(typeToMatch.getName()); + } + } + } + } + ``` + +- 第二段 + + ```java + if (className != null) { + // bean 属性值 + Object evaluated = evaluateBeanDefinitionString(className, mbd); + if (!className.equals(evaluated)) { + // A dynamically resolved expression, supported as of 4.2... + if (evaluated instanceof Class) { + return (Class) evaluated; + } + else if (evaluated instanceof String) { + className = (String) evaluated; + freshResolve = true; + } + else { + throw new IllegalStateException("Invalid class name expression result: " + evaluated); + } + } + ``` + + + + + + + + + +###### evaluateBeanDefinitionString + + + +```java +@Nullable +protected Object evaluateBeanDefinitionString(@Nullable String value, @Nullable BeanDefinition beanDefinition) { + // 占位符解析 + if (this.beanExpressionResolver == null) { + return value; + } + + Scope scope = null; + if (beanDefinition != null) { + // 获取 scope + String scopeName = beanDefinition.getScope(); + if (scopeName != null) { + // scope 转换成 接口值 + scope = getRegisteredScope(scopeName); + } + } + // 返回对象 + return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope)); +} +``` + + + + + +###### evaluate + + + +- `org.springframework.context.expression.StandardBeanExpressionResolver#evaluate` + + + + + +```java + @Override + @Nullable + public Object evaluate(@Nullable String value, BeanExpressionContext evalContext) throws BeansException { + if (!StringUtils.hasLength(value)) { + return value; + } + try { + Expression expr = this.expressionCache.get(value); + if (expr == null) { + // el表达式解析 + expr = this.expressionParser.parseExpression(value, this.beanExpressionParserContext); + // 解析结果放入缓存 + this.expressionCache.put(value, expr); + } + // spring 中默认的表达式上下文 + StandardEvaluationContext sec = this.evaluationCache.get(evalContext); + if (sec == null) { + // 设置属性 + sec = new StandardEvaluationContext(evalContext); + sec.addPropertyAccessor(new BeanExpressionContextAccessor()); + sec.addPropertyAccessor(new BeanFactoryAccessor()); + sec.addPropertyAccessor(new MapAccessor()); + sec.addPropertyAccessor(new EnvironmentAccessor()); + sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory())); + sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader())); + ConversionService conversionService = evalContext.getBeanFactory().getConversionService(); + if (conversionService != null) { + sec.setTypeConverter(new StandardTypeConverter(conversionService)); + } + customizeEvaluationContext(sec); + this.evaluationCache.put(evalContext, sec); + } + // 把值获取 + return expr.getValue(sec); + } + catch (Throwable ex) { + throw new BeanExpressionException("Expression parsing failed", ex); + } + } + +``` + +- 类图 + +![](/images/spring/TemplateAwareExpressionParser.png) + + + +###### BeanExpressionContext + +- 两个属性 + + + +```java +private final ConfigurableBeanFactory beanFactory; + +@Nullable +private final Scope scope; +``` + + + +- 几个方法 + + + +```java +public boolean containsObject(String key) { + return (this.beanFactory.containsBean(key) || + (this.scope != null && this.scope.resolveContextualObject(key) != null)); +} + +@Nullable +public Object getObject(String key) { + if (this.beanFactory.containsBean(key)) { + return this.beanFactory.getBean(key); + } + else if (this.scope != null) { + return this.scope.resolveContextualObject(key); + } + else { + return null; + } +} +``` + +beanName 是否存在 + +根据 beanName 获取 bean 实例 + + + + + +- 回到解析方法 + + + +###### parseExpression + +```java +@Override +public Expression parseExpression(String expressionString, @Nullable ParserContext context) throws ParseException { + if (context != null && context.isTemplate()) { + // 是否使用 template 解析 + return parseTemplate(expressionString, context); + } + else { + // 自定义的解析规则 + return doParseExpression(expressionString, context); + } +} +``` + + + +- doParseExpression + - spring 中的两种解析方式 + - `org.springframework.expression.spel.standard.InternalSpelExpressionParser#doParseExpression ` + - `org.springframework.expression.spel.standard.SpelExpressionParser#doParseExpression` + + + +- parseTemplate 方法 + - `org.springframework.expression.common.TemplateAwareExpressionParser#parseTemplate` + + + + + +```java +private Expression parseTemplate(String expressionString, ParserContext context) throws ParseException { + // 表达式为空 + if (expressionString.isEmpty()) { + // 创建空的 LiteralExpression + return new LiteralExpression(""); + } + + // 表达式解析成接口 + Expression[] expressions = parseExpressions(expressionString, context); + if (expressions.length == 1) { + return expressions[0]; + } + else { + // 返回字符串的表达式 + return new CompositeStringExpression(expressionString, expressions); + } +} +``` + + + +![image-20200903111128603](images/image-20200903111128603.png) + + + +- `parseExpressions` + - `org.springframework.expression.common.TemplateAwareExpressionParser#parseExpressions` + - 说简单一些这个地方就是拿出表达式的值 + + + + + +- 回到 `evaluate` 方法 + + + + + +```java +StandardEvaluationContext sec = this.evaluationCache.get(evalContext); +if (sec == null) { + // 设置属性 + sec = new StandardEvaluationContext(evalContext); + sec.addPropertyAccessor(new BeanExpressionContextAccessor()); + sec.addPropertyAccessor(new BeanFactoryAccessor()); + sec.addPropertyAccessor(new MapAccessor()); + sec.addPropertyAccessor(new EnvironmentAccessor()); + sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory())); + sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader())); + ConversionService conversionService = evalContext.getBeanFactory().getConversionService(); + if (conversionService != null) { + sec.setTypeConverter(new StandardTypeConverter(conversionService)); + } + customizeEvaluationContext(sec); + this.evaluationCache.put(evalContext, sec); +} +// 把值获取 +return expr.getValue(sec); +``` + + + +- 最后一句 `getValue` + + - `org.springframework.expression.common.LiteralExpression#getValue(org.springframework.expression.EvaluationContext)` + + 刚才流程中我们可以看到 `expr` 是`LiteralExpression` + + ```java + @Override + public String getValue(EvaluationContext context) { + return this.literalValue; + } + ``` + + 直接返回字符串. 这个字符串就是刚才放进去的 el表达式 + + + + + +往外跳 找到方法 `doResolveBeanClass` + + + +```java +if (className != null) { + // bean 属性值 + Object evaluated = evaluateBeanDefinitionString(className, mbd); + if (!className.equals(evaluated)) { + // A dynamically resolved expression, supported as of 4.2... + if (evaluated instanceof Class) { + return (Class) evaluated; + } + else if (evaluated instanceof String) { + className = (String) evaluated; + freshResolve = true; + } + else { + throw new IllegalStateException("Invalid class name expression result: " + evaluated); + } + } + if (freshResolve) { + // When resolving against a temporary class loader, exit early in order + // to avoid storing the resolved Class in the bean definition. + if (dynamicLoader != null) { + try { + return dynamicLoader.loadClass(className); + } + catch (ClassNotFoundException ex) { + if (logger.isTraceEnabled()) { + logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex); + } + } + } + return ClassUtils.forName(className, dynamicLoader); + } +} + +``` + +- 目前为止我们解析了 第一句话 `Object evaluated = evaluateBeanDefinitionString(className, mbd);` 接下来往下走看一下具体的 class 返回对象 + + + +1. 类型等于 class 直接返回 +2. 类型等于 String 的两种返回方式 + 1. ClassLoader.loadClass 返回 + 2. ClassUtils.forName 返回 + 1. 底层方法为 `java.lang.Class#forName(java.lang.String, boolean, java.lang.ClassLoader)` + + + + + +###### resolveBeanClass + +- 回到`doResolveBeanClass`方法中.最后一行 + + ```java + // Resolve regularly, caching the result in the BeanDefinition... + return mbd.resolveBeanClass(beanClassLoader); + ``` + + + +```java +@Nullable +public Class resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException { + // 获取beanClassName + String className = getBeanClassName(); + if (className == null) { + return null; + } + // 加载类 + Class resolvedClass = ClassUtils.forName(className, classLoader); + this.beanClass = resolvedClass; + // 返回 + return resolvedClass; +} +``` + + + +- 获取 beanClassName + +```java +@Override +@Nullable +public String getBeanClassName() { + Object beanClassObject = this.beanClass; + if (beanClassObject instanceof Class) { + return ((Class) beanClassObject).getName(); + } + else { + return (String) beanClassObject; + } +} +``` + + + + + + + + + +- 回到`createBeanInstance` + - `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance` + + + + + + + +```java +// 返回一个用来创建bean实例的回调接口 +// Supplier get 直接获取bean对象 +Supplier instanceSupplier = mbd.getInstanceSupplier(); +if (instanceSupplier != null) { + return obtainFromSupplier(instanceSupplier, beanName); +} +``` + + + +###### obtainFromSupplier + + + +```java +protected BeanWrapper obtainFromSupplier(Supplier instanceSupplier, String beanName) { + Object instance; + + // 获取当前的bean实例 + String outerBean = this.currentlyCreatedBean.get(); + // 设置当前处理的beanName + this.currentlyCreatedBean.set(beanName); + try { + // 从 Supplier 中获取 + instance = instanceSupplier.get(); + } + finally { + if (outerBean != null) { + // 如果 currentlyCreatedBean 取不到设置 + this.currentlyCreatedBean.set(outerBean); + } + else { + // 移除 + this.currentlyCreatedBean.remove(); + } + } + + if (instance == null) { + // supplier 中获取不到, 将实例设置为 NullBean + instance = new NullBean(); + } + // beanWrapper 包装 + BeanWrapper bw = new BeanWrapperImpl(instance); + // beanWrapper 实例化后的操作 + initBeanWrapper(bw); + return bw; +} +``` + +- `Supplier` 代码如下 + +```java +@FunctionalInterface +public interface Supplier { + + /** + * Gets a result. + * + * @return a result + */ + T get(); +} +``` + + + + + +###### initBeanWrapper + + + +```java +protected void initBeanWrapper(BeanWrapper bw) { + // 设置转换服务 + bw.setConversionService(getConversionService()); + // 注册自定义属性编辑器 + registerCustomEditors(bw); +} +``` + + + + + + + +###### registerCustomEditors + + + +```java +protected void registerCustomEditors(PropertyEditorRegistry registry) { + PropertyEditorRegistrySupport registrySupport = + (registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null); + if (registrySupport != null) { + registrySupport.useConfigValueEditors(); + } + if (!this.propertyEditorRegistrars.isEmpty()) { + for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) { + try { + // 属性编辑器,注册自定义属性编辑器 + registrar.registerCustomEditors(registry); + } + catch (BeanCreationException ex) { + Throwable rootCause = ex.getMostSpecificCause(); + if (rootCause instanceof BeanCurrentlyInCreationException) { + BeanCreationException bce = (BeanCreationException) rootCause; + String bceBeanName = bce.getBeanName(); + if (bceBeanName != null && isCurrentlyInCreation(bceBeanName)) { + if (logger.isDebugEnabled()) { + logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() + + "] failed because it tried to obtain currently created bean '" + + ex.getBeanName() + "': " + ex.getMessage()); + } + onSuppressedException(ex); + continue; + } + } + throw ex; + } + } + } + if (!this.customEditors.isEmpty()) { + this.customEditors.forEach((requiredType, editorClass) -> + registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass))); + } +} +``` + + + +- 最后调用 + + `org.springframework.beans.support.ResourceEditorRegistrar#registerCustomEditors` + + + +###### registerCustomEditors + +```java +@Override +public void registerCustomEditors(PropertyEditorRegistry registry) { + ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver); + doRegisterEditor(registry, Resource.class, baseEditor); + doRegisterEditor(registry, ContextResource.class, baseEditor); + doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor)); + doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor)); + doRegisterEditor(registry, File.class, new FileEditor(baseEditor)); + doRegisterEditor(registry, Path.class, new PathEditor(baseEditor)); + doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor)); + doRegisterEditor(registry, URL.class, new URLEditor(baseEditor)); + + ClassLoader classLoader = this.resourceLoader.getClassLoader(); + doRegisterEditor(registry, URI.class, new URIEditor(classLoader)); + doRegisterEditor(registry, Class.class, new ClassEditor(classLoader)); + doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader)); + + if (this.resourceLoader instanceof ResourcePatternResolver) { + doRegisterEditor(registry, Resource[].class, + new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver)); + } +} +``` + + + +###### doRegisterEditor + + + +```java +private void doRegisterEditor(PropertyEditorRegistry registry, Class requiredType, PropertyEditor editor) { + if (registry instanceof PropertyEditorRegistrySupport) { + // 属性编辑器覆盖默认的编辑器 + ((PropertyEditorRegistrySupport) registry).overrideDefaultEditor(requiredType, editor); + } + else { + // 注册自定义的属性编辑器 + registry.registerCustomEditor(requiredType, editor); + } +} +``` + + + +覆盖默认编辑器 + +```java +public void overrideDefaultEditor(Class requiredType, PropertyEditor propertyEditor) { + if (this.overriddenDefaultEditors == null) { + this.overriddenDefaultEditors = new HashMap<>(); + } + this.overriddenDefaultEditors.put(requiredType, propertyEditor); +} +``` + + + +- `registerCustomEditor` + +```JAVA +@Override +public void registerCustomEditor(@Nullable Class requiredType, @Nullable String propertyPath, PropertyEditor propertyEditor) { + if (requiredType == null && propertyPath == null) { + throw new IllegalArgumentException("Either requiredType or propertyPath is required"); + } + if (propertyPath != null) { + if (this.customEditorsForPath == null) { + this.customEditorsForPath = new LinkedHashMap<>(16); + } + this.customEditorsForPath.put(propertyPath, new CustomEditorHolder(propertyEditor, requiredType)); + } + else { + if (this.customEditors == null) { + this.customEditors = new LinkedHashMap<>(16); + } + // 放入 customEditors map对象中 + this.customEditors.put(requiredType, propertyEditor); + this.customEditorCache = null; + } +} +``` + + + + + +到这里 `createBeanInstance` 流程已经完毕 + +回到`doCreateBean` 方法 + + + + + +```java +// beanWrapper 是否存在 +if (instanceWrapper == null) { + // 创建 bean 实例 + instanceWrapper = createBeanInstance(beanName, mbd, args); +} +// 获取 实例 +final Object bean = instanceWrapper.getWrappedInstance(); +// beanWrapper中存储的实例.class +Class beanType = instanceWrapper.getWrappedClass(); +if (beanType != NullBean.class) { + mbd.resolvedTargetType = beanType; +} +``` + +紧接着两行代码 获取 bean 实例 和beanType + + + + + + + +###### applyMergedBeanDefinitionPostProcessors + +```java +synchronized (mbd.postProcessingLock) { + if (!mbd.postProcessed) { + try { + // 后置方法执行 BeanPostProcessor + applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); + } + catch (Throwable ex) { + throw new BeanCreationException(mbd.getResourceDescription(), beanName, + "Post-processing of merged bean definition failed", ex + ); + } + mbd.postProcessed = true; + } +} +``` + +- `applyMergedBeanDefinitionPostProcessors` 方法会执行所有的后置方法. + +```java +protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class beanType, String beanName) { + for (BeanPostProcessor bp : getBeanPostProcessors()) { + if (bp instanceof MergedBeanDefinitionPostProcessor) { + MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp; + bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); + } + } +} +``` + + + + + + + +###### addSingletonFactory + +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingletonFactory` + +- 继续回到 doCreateBean + + + +```java +// Eagerly cache singletons to be able to resolve circular references +// even when triggered by lifecycle interfaces like BeanFactoryAware. +boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && + isSingletonCurrentlyInCreation(beanName)); + +// 单例对象暴露 +if (earlySingletonExposure) { + if (logger.isTraceEnabled()) { + logger.trace("Eagerly caching bean '" + beanName + + "' to allow for resolving potential circular references"); + } + addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); +} +``` + +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingletonFactory` + + 添加单例工厂 + +```java +protected void addSingletonFactory(String beanName, ObjectFactory singletonFactory) { + Assert.notNull(singletonFactory, "Singleton factory must not be null"); + synchronized (this.singletonObjects) { + if (!this.singletonObjects.containsKey(beanName)) { + // 添加单例对象工厂 + this.singletonFactories.put(beanName, singletonFactory); + // 删除单例BeanName + this.earlySingletonObjects.remove(beanName); + // 注册单例beanName + this.registeredSingletons.add(beanName); + } + } +} +``` + + + + + + + +###### getEarlyBeanReference + + + +- `org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getEarlyBeanReference` + +```java +@Override +public Object getEarlyBeanReference(Object bean, String beanName) { + // 尝试获取缓存 + Object cacheKey = getCacheKey(bean.getClass(), beanName); + // 加入缓存 + this.earlyProxyReferences.put(cacheKey, bean); + // 代理对象 + return wrapIfNecessary(bean, beanName, cacheKey); +} +``` + + + +- wrapIfNecessary + +```java +protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { + // 这个bean是否处理过 + if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { + return bean; + } + // 这个bean是否需要代理 + if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { + return bean; + } + // 1.bean.class是否是Spring接口类型 2. 是否为 AutowireCapableBeanFactory 接口 + if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { + // 向代理集合中插入值 + this.advisedBeans.put(cacheKey, Boolean.FALSE); + return bean; + } + + // Create proxy if we have advice. + // 增强方法获取 + Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); + // 增强方法不为空 + if (specificInterceptors != DO_NOT_PROXY) { + // 向代理集合中插入值 + this.advisedBeans.put(cacheKey, Boolean.TRUE); + // 创建代理 + Object proxy = createProxy( + bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); + // 代理类型 + this.proxyTypes.put(cacheKey, proxy.getClass()); + return proxy; + } + + this.advisedBeans.put(cacheKey, Boolean.FALSE); + return bean; +} +``` + + + +- 回到下面代码中 + + ```java + if (earlySingletonExposure) { + if (logger.isTraceEnabled()) { + logger.trace("Eagerly caching bean '" + beanName + + "' to allow for resolving potential circular references"); + } + // 添加单例工厂 + addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); + } + ``` + + - 上述方法就是将结果bean放入 + + + + + + + +###### populateBean + +```java +// Initialize the bean instance. +Object exposedObject = bean; +try { + populateBean(beanName, mbd, instanceWrapper); + exposedObject = initializeBean(beanName, exposedObject, mbd); +} +``` + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean` +- 设置属性值 + + + + + +- 概述一下方法 + + - 自动注入的两种实现 + + 1. 根据类型 + 2. 根据名称 + + - xml 中的属性标签设置 + + ```xml + + + + ``` + + ```java + { + if (bw == null) { + if (mbd.hasPropertyValues()) { + throw new BeanCreationException( + mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); + } + else { + // Skip property population phase for null instance. + return; + } + } + + // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the + // state of the bean before properties are set. This can be used, for example, + // to support styles of field injection. + if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { + for (BeanPostProcessor bp : getBeanPostProcessors()) { + if (bp instanceof InstantiationAwareBeanPostProcessor) { + InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; + if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { + return; + } + } + } + } + + PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); + // 获取自动注入的值 + int resolvedAutowireMode = mbd.getResolvedAutowireMode(); + // 自动注入 + if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { + MutablePropertyValues newPvs = new MutablePropertyValues(pvs); + // Add property values based on autowire by name if applicable. + if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { + // 按照名称注入 + autowireByName(beanName, mbd, bw, newPvs); + } + // Add property values based on autowire by type if applicable. + if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { + // 按照类型注入 + autowireByType(beanName, mbd, bw, newPvs); + } + pvs = newPvs; + } + + boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); + boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); + + PropertyDescriptor[] filteredPds = null; + if (hasInstAwareBpps) { + if (pvs == null) { + pvs = mbd.getPropertyValues(); + } + for (BeanPostProcessor bp : getBeanPostProcessors()) { + if (bp instanceof InstantiationAwareBeanPostProcessor) { + InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; + PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); + if (pvsToUse == null) { + if (filteredPds == null) { + filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); + } + pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); + if (pvsToUse == null) { + return; + } + } + pvs = pvsToUse; + } + } + } + if (needsDepCheck) { + if (filteredPds == null) { + filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); + } + // 以来检查 + checkDependencies(beanName, mbd, filteredPds, pvs); + } + + if (pvs != null) { + // 应用属性 + applyPropertyValues(beanName, mbd, bw, pvs); + } + } + ``` + + + + + +pvs 属性如下 + +![image-20200903150738285](images/image-20200903150738285.png) + + + +###### applyPropertyValues + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyPropertyValues` +- 属性设置 + +```java +protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { + if (pvs.isEmpty()) { + return; + } + + if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) { + ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); + } + + MutablePropertyValues mpvs = null; + // 没有解析的属性 + List original; + + if (pvs instanceof MutablePropertyValues) { + mpvs = (MutablePropertyValues) pvs; + if (mpvs.isConverted()) { + // Shortcut: use the pre-converted values as-is. + try { + bw.setPropertyValues(mpvs); + return; + } + catch (BeansException ex) { + throw new BeanCreationException( + mbd.getResourceDescription(), beanName, "Error setting property values", ex); + } + } + original = mpvs.getPropertyValueList(); + } + else { + original = Arrays.asList(pvs.getPropertyValues()); + } + + // 自定义转换器 + TypeConverter converter = getCustomTypeConverter(); + if (converter == null) { + converter = bw; + } + // 创建BeanDefinitionValueResolver + BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); + + // Create a deep copy, resolving any references for values. + // 解析后的对象集合 + List deepCopy = new ArrayList<>(original.size()); + boolean resolveNecessary = false; + for (PropertyValue pv : original) { + // 解析过的属性 + if (pv.isConverted()) { + deepCopy.add(pv); + } + // 没有解析过的属性 + else { + // 属性名称 + String propertyName = pv.getName(); + // 属性值,直接读取到的 + Object originalValue = pv.getValue(); + if (originalValue == AutowiredPropertyMarker.INSTANCE) { + Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod(); + if (writeMethod == null) { + throw new IllegalArgumentException("Autowire marker for property without write method: " + pv); + } + originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true); + } + // 解析值 + Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); + Object convertedValue = resolvedValue; + + /** + * 1. isWritableProperty: 属性可写 + * 2. isNestedOrIndexedProperty: 是否循环嵌套 + */ + boolean convertible = bw.isWritableProperty(propertyName) && + !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); + if (convertible) { + // 转换器解析 + convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); + } + // Possibly store converted value in merged bean definition, + // in order to avoid re-conversion for every created bean instance. + if (resolvedValue == originalValue) { + if (convertible) { + pv.setConvertedValue(convertedValue); + } + deepCopy.add(pv); + } + // 类型解析 + else if (convertible && originalValue instanceof TypedStringValue && + !((TypedStringValue) originalValue).isDynamic() && + !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) { + pv.setConvertedValue(convertedValue); + deepCopy.add(pv); + } + else { + resolveNecessary = true; + deepCopy.add(new PropertyValue(pv, convertedValue)); + } + } + } + if (mpvs != null && !resolveNecessary) { + mpvs.setConverted(); + } + + // Set our (possibly massaged) deep copy. + try { + bw.setPropertyValues(new MutablePropertyValues(deepCopy)); + } + catch (BeansException ex) { + throw new BeanCreationException( + mbd.getResourceDescription(), beanName, "Error setting property values", ex); + } +} +``` + + + + + + + +属性设置后跳出方法回到 `doCreateBean` + +```java +try { + populateBean(beanName, mbd, instanceWrapper); + exposedObject = initializeBean(beanName, exposedObject, mbd); +} +``` + +![image-20200903150930186](images/image-20200903150930186.png) + + + + + + + + + +###### initializeBean + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)` + + + +- 我们可以看一下整个代码的流程 + 1. aware 接口的执行 + 2. BeanPostProcessor 前置方法执行 + 3. bean实例化 + 4. BeanPostProcessor 后置方法执行 + 5. 返回bean + +```java +protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { + if (System.getSecurityManager() != null) { + AccessController.doPrivileged((PrivilegedAction) () -> { + invokeAwareMethods(beanName, bean); + return null; + }, getAccessControlContext()); + } + else { + // aware 接口执行 + invokeAwareMethods(beanName, bean); + } + + Object wrappedBean = bean; + if (mbd == null || !mbd.isSynthetic()) { + // BeanPostProcessor 前置方法执行 + wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); + } + + try { + // 执行实例化函数 + invokeInitMethods(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()) { + // BeanPostProcessor 后置方法执行 + wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); + } + + return wrappedBean; +} +``` + + + + + +- Aware 接口的执行 + +```java +private void invokeAwareMethods(final String beanName, final Object bean) { + if (bean instanceof Aware) { + if (bean instanceof BeanNameAware) { + ((BeanNameAware) bean).setBeanName(beanName); + } + if (bean instanceof BeanClassLoaderAware) { + ClassLoader bcl = getBeanClassLoader(); + if (bcl != null) { + ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); + } + } + if (bean instanceof BeanFactoryAware) { + ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); + } + } +}j +``` + + + +- 前置方法执行 + + ```java + @Override + public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) + throws BeansException { + + Object result = existingBean; + for (BeanPostProcessor processor : getBeanPostProcessors()) { + Object current = processor.postProcessBeforeInitialization(result, beanName); + if (current == null) { + return result; + } + result = current; + } + return result; + } + ``` + +- 后置方法执行 + + ```java + @Override + public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) + throws BeansException { + + Object result = existingBean; + for (BeanPostProcessor processor : getBeanPostProcessors()) { + // 执行 spring 容器中 BeanPostProcessor + Object current = processor.postProcessAfterInitialization(result, beanName); + if (current == null) { + return result; + } + result = current; + } + return result; + } + ``` + + + + + + + +###### invokeInitMethods + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods` +- 初始化方法重点看一下 + + + + + +```java +protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) + throws Throwable { + + + // 是否是 InitializingBean + boolean isInitializingBean = (bean instanceof InitializingBean); + // 是否存在方法 "afterPropertiesSet" + if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { + if (logger.isTraceEnabled()) { + logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); + } + if (System.getSecurityManager() != null) { + try { + // 执行 afterPropertiesSet + AccessController.doPrivileged((PrivilegedExceptionAction) () -> { + ((InitializingBean) bean).afterPropertiesSet(); + return null; + }, getAccessControlContext()); + } + catch (PrivilegedActionException pae) { + throw pae.getException(); + } + } + else { + ((InitializingBean) bean).afterPropertiesSet(); + } + } + + if (mbd != null && bean.getClass() != NullBean.class) { + String initMethodName = mbd.getInitMethodName(); + if (StringUtils.hasLength(initMethodName) && + !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && + !mbd.isExternallyManagedInitMethod(initMethodName)) { + // 自定义的 init method + invokeCustomInitMethod(beanName, bean, mbd); + } + } +} +``` + + + + + +![image-20200903153057321](images/image-20200903153057321.png) + +我们现在的bean不是`InitializingBean` 会走自定义的`init-mthod`方法 + +- 做一下改造实体对象 + + ```java + public void initMethod() { + this.name = "abc"; + this.age = 10; + } + ``` + + + +```xml + + + +``` + +- 观察 `initMethodName` 会变成 标签属性`init-method` 的内容. 接下来就是通过反射执行方法 + +![image-20200903153432559](images/image-20200903153432559.png) + + + + + +- 在执行方法前将 bean 的信息先做一次截图 + + ![image-20200903153533141](images/image-20200903153533141.png) + +- 如果按照我们代码中的编写方式 bean 的属性会被覆盖 + + ![image-20200903153617353](images/image-20200903153617353.png) + + + + + +###### invokeCustomInitMethod + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeCustomInitMethod` +- 执行 自定义的`init-method` 方法 + + + + + +```java +protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) + throws Throwable { + + // 获取 initMethod 名称 + String initMethodName = mbd.getInitMethodName(); + Assert.state(initMethodName != null, "No init method set"); + // 反射获取方法 + Method initMethod = (mbd.isNonPublicAccessAllowed() ? + BeanUtils.findMethod(bean.getClass(), initMethodName) : + ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName)); + + // 方法是否存在判断 + if (initMethod == null) { + if (mbd.isEnforceInitMethod()) { + throw new BeanDefinitionValidationException("Could not find an init method named '" + + initMethodName + "' on bean with name '" + beanName + "'"); + } + else { + if (logger.isTraceEnabled()) { + logger.trace("No default init method named '" + initMethodName + + "' found on bean with name '" + beanName + "'"); + } + // Ignore non-existent default lifecycle methods. + return; + } + } + + if (logger.isTraceEnabled()) { + logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'"); + } + // 尝试获取接口方法 + Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod); + + if (System.getSecurityManager() != null) { + AccessController.doPrivileged((PrivilegedAction) () -> { + ReflectionUtils.makeAccessible(methodToInvoke); + return null; + }); + try { + // 反射调用 + AccessController.doPrivileged((PrivilegedExceptionAction) () -> + methodToInvoke.invoke(bean), getAccessControlContext()); + } + catch (PrivilegedActionException pae) { + InvocationTargetException ex = (InvocationTargetException) pae.getException(); + throw ex.getTargetException(); + } + } + else { + try { + // 反射调用 + ReflectionUtils.makeAccessible(methodToInvoke); + methodToInvoke.invoke(bean); + } + catch (InvocationTargetException ex) { + throw ex.getTargetException(); + } + } +} +``` + + + + + + + +###### getInterfaceMethodIfPossible + + + +- `org.springframework.util.ClassUtils#getInterfaceMethodIfPossible` + +```java +public static Method getInterfaceMethodIfPossible(Method method) { + // 是不是 public + // 是不是 接口 + if (!Modifier.isPublic(method.getModifiers()) || method.getDeclaringClass().isInterface()) { + return method; + } + // 放入init-method 缓存 + return interfaceMethodCache.computeIfAbsent(method, key -> { + Class current = key.getDeclaringClass(); + while (current != null && current != Object.class) { + // 当前类的 接口列表 + Class[] ifcs = current.getInterfaces(); + for (Class ifc : ifcs) { + try { + // 从接口中获取方法 + return ifc.getMethod(key.getName(), key.getParameterTypes()); + } + catch (NoSuchMethodException ex) { + // ignore + } + } + current = current.getSuperclass(); + } + return key; + }); +} +``` + + + + + + + +- 跳出这个方法`initializeBean` 回到下面代码 + + ```java + try { + populateBean(beanName, mbd, instanceWrapper); + exposedObject = initializeBean(beanName, exposedObject, mbd); + } + ``` + + - `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean` + + 其实到此bean已经创建完成可以直接返回了. + + + + + + + + + + + +- 再往外层跳 + + `org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean` + + ```javascript + if (mbd.isSingleton()) { + // 判断是否是单例 + sharedInstance = getSingleton(beanName, () -> { + try { + return createBean(beanName, mbd, args); + } + catch (BeansException ex) { + // Explicitly remove instance from singleton cache: It might have been put there + // eagerly by the creation process, to allow for circular reference resolution. + // Also remove any beans that received a temporary reference to the bean. + destroySingleton(beanName); + throw ex; + } + }); + bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); + } + ``` + + - 单例对象的创建bean已经完成啦... + + + + + + + +- 其他的两种创建,其本质还是 `createBean` 方法的调用. + +```java +// 原型模式创建 +else if (mbd.isPrototype()) { + // It's a prototype -> create a new instance. + Object prototypeInstance = null; + try { + beforePrototypeCreation(beanName); + prototypeInstance = createBean(beanName, mbd, args); + } + finally { + afterPrototypeCreation(beanName); + } + bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); +} + +else { + String scopeName = mbd.getScope(); + final Scope scope = this.scopes.get(scopeName); + if (scope == null) { + throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); + } + try { + Object scopedInstance = scope.get(beanName, () -> { + beforePrototypeCreation(beanName); + try { + return createBean(beanName, mbd, args); + } + finally { + afterPrototypeCreation(beanName); + } + }); + bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); + } + catch (IllegalStateException ex) { + throw new BeanCreationException(beanName, + "Scope '" + scopeName + "' is not active for the current thread; consider " + + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", + ex); + } +} +``` + + + + + +- 再往外面跳一层 回到 getBean 方法. + +- 终于 getBean 方法底层调用分析结束. \ No newline at end of file diff --git a/docs/SpringBoot/SpringBoot-ConditionalOnBean.md b/docs/SpringBoot/SpringBoot-ConditionalOnBean.md new file mode 100644 index 0000000..90ed72b --- /dev/null +++ b/docs/SpringBoot/SpringBoot-ConditionalOnBean.md @@ -0,0 +1,721 @@ +# SpringBoot ConditionalOnBean +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring-boot](https://github.com/SourceHot/spring-boot-read) + +- 在 SpringBoot 中有下列当XXX存在或不存的时候执行初始化 + - ConditionalOnBean + ConditionalOnClass + ConditionalOnCloudPlatform + ConditionalOnExpression + ConditionalOnJava + ConditionalOnJndi + ConditionalOnMissingBean + ConditionalOnMissingClass + ConditionalOnNotWebApplication + ConditionalOnProperty + ConditionalOnResource + ConditionalOnSingleCandidate + ConditionalOnWebApplication + + + +## ConditionalOnBean + +```java +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Conditional(OnBeanCondition.class) +public @interface ConditionalOnBean { + + /** + * 需要匹配的 bean 类型 + */ + Class[] value() default {}; + + /** + * 需要匹配的 bean 类型 + */ + String[] type() default {}; + + /** + * 匹配的 bean 注解 + */ + Class[] annotation() default {}; + + /** + * 需要匹配的 beanName + */ + String[] name() default {}; + + /** + * 搜索策略 + */ + SearchStrategy search() default SearchStrategy.ALL; + + /** + */ + Class[] parameterizedContainer() default {}; + +} +``` + + + + + +## SearchStrategy + +```java +public enum SearchStrategy { + + /** + * 当前 上下文 + */ + CURRENT, + + /** + * 找所有的父容器 + */ + ANCESTORS, + + /** + * 当前上下文+父容器 + */ + ALL + +} +``` + + + + + +## OnBeanCondition + +- org.springframework.boot.autoconfigure.condition.OnBeanCondition + +- 这个类是一个条件类,相关的还有 + + ```properties + org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\ + org.springframework.boot.autoconfigure.condition.OnBeanCondition,\ + org.springframework.boot.autoconfigure.condition.OnClassCondition,\ + org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition + ``` + + + + + +- 类图 + + ![image-20200824085726621](//images/SpringBoot//SpringBoot/image-20200824085726621.png) + + + + + +在看这部分源码之前需要先了解 `Conditional`和`Condition`的源码 + +- 简单描述 + + 通过实现`Condition` 来确认是否初始化bean + + + +- 从类图上我们可以看到 `condition` 的继承关系. 在这里需要去找到`SpringBootCondition` + + + +- `org.springframework.boot.autoconfigure.condition.SpringBootCondition#matches(org.springframework.context.annotation.ConditionContext, org.springframework.core.type.AnnotatedTypeMetadata)` + + ```java + @Override + public final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + // 类名或者方法名标记 + String classOrMethodName = getClassOrMethodName(metadata); + try { + // 比较类,子类实现 + ConditionOutcome outcome = getMatchOutcome(context, metadata); + // 日志输出 + logOutcome(classOrMethodName, outcome); + // 报告记录 + recordEvaluation(context, classOrMethodName, outcome); + // 返回匹配结果 + return outcome.isMatch(); + } + catch (NoClassDefFoundError ex) { + throw new IllegalStateException("Could not evaluate condition on " + classOrMethodName + " due to " + + ex.getMessage() + " not found. Make sure your own configuration does not rely on " + + "that class. This can also happen if you are " + + "@ComponentScanning a springframework package (e.g. if you " + + "put a @ComponentScan in the default package by mistake)", ex); + } + catch (RuntimeException ex) { + throw new IllegalStateException("Error processing condition on " + getName(metadata), ex); + } + } + ``` + + + + + +- `getOutcomes` 子类实现 + + `org.springframework.boot.autoconfigure.condition.OnBeanCondition#getOutcomes` + + ```java + String[] autoConfigurationClasses, + AutoConfigurationMetadata autoConfigurationMetadata + ``` + + - 第一个参数: 需要自动配置的类 + - 配置注解信息 + + + + + +### ConditionOutcome 和 ConditionMessage + + + +```java +public class ConditionOutcome { + + /** + * 是否匹配 + */ + private final boolean match; + /** + * 条件信息 + */ + private final ConditionMessage message; +} + + +public final class ConditionMessage { + + private String message; +} +``` + + + + + +- 造一个对象用来进行debug + +```java + +@Component +public class Beans { + + + @Bean + public A a() { + return new A(); + } + + + @Bean + @ConditionalOnBean(value = A.class) + public B b() { + return new B(); + } +} + +``` + + + +## getMatchOutcome + +```java +@Override +public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { + // 条件信息 + ConditionMessage matchMessage = ConditionMessage.empty(); + // 获取注解求和 + MergedAnnotations annotations = metadata.getAnnotations(); + // 注解是否匹配 + if (annotations.isPresent(ConditionalOnBean.class)) { + // 搜索 ConditionalOnBean 注解 + Spec spec = new Spec<>(context, metadata, annotations, + ConditionalOnBean.class); + // 匹配结果 + MatchResult matchResult = getMatchingBeans(context, spec); + if (!matchResult.isAllMatched()) { + String reason = createOnBeanNoMatchReason(matchResult); + return ConditionOutcome.noMatch(spec.message().because(reason)); + } + // 把注解解析出来获得文本 + matchMessage = spec.message(matchMessage).found("bean", "beans").items(Style.QUOTE, + matchResult.getNamesOfAllMatches()); + } + if (metadata.isAnnotated(ConditionalOnSingleCandidate.class.getName())) { + Spec spec = new SingleCandidateSpec(context, metadata, annotations); + MatchResult matchResult = getMatchingBeans(context, spec); + if (!matchResult.isAllMatched()) { + return ConditionOutcome.noMatch(spec.message().didNotFind("any beans").atAll()); + } + else if (!hasSingleAutowireCandidate(context.getBeanFactory(), matchResult.getNamesOfAllMatches(), + spec.getStrategy() == SearchStrategy.ALL)) { + return ConditionOutcome.noMatch(spec.message().didNotFind("a primary bean from beans") + .items(Style.QUOTE, matchResult.getNamesOfAllMatches())); + } + matchMessage = spec.message(matchMessage).found("a primary bean from beans").items(Style.QUOTE, + matchResult.getNamesOfAllMatches()); + } + if (metadata.isAnnotated(ConditionalOnMissingBean.class.getName())) { + Spec spec = new Spec<>(context, metadata, annotations, + ConditionalOnMissingBean.class); + MatchResult matchResult = getMatchingBeans(context, spec); + if (matchResult.isAnyMatched()) { + String reason = createOnMissingBeanNoMatchReason(matchResult); + return ConditionOutcome.noMatch(spec.message().because(reason)); + } + matchMessage = spec.message(matchMessage).didNotFind("any beans").atAll(); + } + return ConditionOutcome.match(matchMessage); +} +``` + + + +- 开始方法分析 + + + +### getMatchingBeans + + + +- `org.springframework.boot.autoconfigure.condition.OnBeanCondition#getMatchingBeans` + + + + + +```java +protected final MatchResult getMatchingBeans(ConditionContext context, Spec spec) { + // 获取上下文 + ClassLoader classLoader = context.getClassLoader(); + // 获取 IOC 容器 + ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); + // 扫描方式比较是否为当前上下文 + boolean considerHierarchy = spec.getStrategy() != SearchStrategy.CURRENT; + + Set> parameterizedContainers = spec.getParameterizedContainers(); + if (spec.getStrategy() == SearchStrategy.ANCESTORS) { + BeanFactory parent = beanFactory.getParentBeanFactory(); + Assert.isInstanceOf(ConfigurableListableBeanFactory.class, parent, + "Unable to use SearchStrategy.ANCESTORS"); + beanFactory = (ConfigurableListableBeanFactory) parent; + } + // 结果对象初始化 + MatchResult result = new MatchResult(); + Set beansIgnoredByType = getNamesOfBeansIgnoredByType(classLoader, beanFactory, considerHierarchy, + spec.getIgnoredTypes(), parameterizedContainers); + for (String type : spec.getTypes()) { + // 通过类型获取 beanName + Collection typeMatches = getBeanNamesForType(classLoader, considerHierarchy, beanFactory, type, + parameterizedContainers); + typeMatches.removeAll(beansIgnoredByType); + if (typeMatches.isEmpty()) { + result.recordUnmatchedType(type); + } + else { + result.recordMatchedType(type, typeMatches); + } + } + for (String annotation : spec.getAnnotations()) { + Set annotationMatches = getBeanNamesForAnnotation(classLoader, beanFactory, annotation, + considerHierarchy); + annotationMatches.removeAll(beansIgnoredByType); + if (annotationMatches.isEmpty()) { + result.recordUnmatchedAnnotation(annotation); + } + else { + result.recordMatchedAnnotation(annotation, annotationMatches); + } + } + for (String beanName : spec.getNames()) { + if (!beansIgnoredByType.contains(beanName) && containsBean(beanFactory, beanName, considerHierarchy)) { + result.recordMatchedName(beanName); + } + else { + result.recordUnmatchedName(beanName); + } + } + return result; +} +``` + + + +- 在`MatchResult result = new MatchResult()` 之前的代码作用是确认ioc容器 + +#### getNamesOfBeansIgnoredByType + +```java + /** + * 获取忽略的beans(返回对象是 beanName) + * 循环,忽略的类型, 将类型从 beanFactory 获取,返回 + */ + private Set getNamesOfBeansIgnoredByType(ClassLoader classLoader, ListableBeanFactory beanFactory, + boolean considerHierarchy, Set ignoredTypes, Set> parameterizedContainers) { + Set result = null; + for (String ignoredType : ignoredTypes) { + // 从 beanFactory 中获取忽略的beanNames + Collection ignoredNames = getBeanNamesForType(classLoader, considerHierarchy, beanFactory, + ignoredType, parameterizedContainers); + result = addAll(result, ignoredNames); + } + return (result != null) ? result : Collections.emptySet(); + } + +``` + + + + + + + +#### getBeanNamesForType + + + +```java +/** + * 通过类型获取 beanName + */ +private Set getBeanNamesForType(ClassLoader classLoader, boolean considerHierarchy, + ListableBeanFactory beanFactory, String type, Set> parameterizedContainers) throws LinkageError { + try { + // 从beanFactory 中获取忽略的类 返回beanNanme + return getBeanNamesForType(beanFactory, considerHierarchy, resolve(type, classLoader), + parameterizedContainers); + } + catch (ClassNotFoundException | NoClassDefFoundError ex) { + return Collections.emptySet(); + } +} +``` + + + + + +#### getBeanNamesForType + + + +```java +/** + * 通过类型获取 beanName + */ +private Set getBeanNamesForType(ListableBeanFactory beanFactory, boolean considerHierarchy, Class type, + Set> parameterizedContainers) { + // 获取beanName + Set result = collectBeanNamesForType(beanFactory, considerHierarchy, type, parameterizedContainers, + null); + return (result != null) ? result : Collections.emptySet(); +} +``` + + + +#### collectBeanNamesForType + +- 这里最终回到了spring beanFactory 的方法 getBeanNamesForType + +```java +private Set collectBeanNamesForType(ListableBeanFactory beanFactory, boolean considerHierarchy, + Class type, Set> parameterizedContainers, Set result) { + result = addAll(result, beanFactory.getBeanNamesForType(type, true, false)); + for (Class container : parameterizedContainers) { + ResolvableType generic = ResolvableType.forClassWithGenerics(container, type); + result = addAll(result, beanFactory.getBeanNamesForType(generic, true, false)); + } + if (considerHierarchy && beanFactory instanceof HierarchicalBeanFactory) { + BeanFactory parent = ((HierarchicalBeanFactory) beanFactory).getParentBeanFactory(); + if (parent instanceof ListableBeanFactory) { + result = collectBeanNamesForType((ListableBeanFactory) parent, considerHierarchy, type, + parameterizedContainers, result); + } + } + return result; +} +``` + + + +到这里需要忽略的beanName 就全部找出来了 + + + + + + + +```java +// 匹配类型在移除 +for (String type : spec.getTypes()) { + // 通过类型获取 beanName + Collection typeMatches = getBeanNamesForType(classLoader, considerHierarchy, beanFactory, type, + parameterizedContainers); + typeMatches.removeAll(beansIgnoredByType); + if (typeMatches.isEmpty()) { + result.recordUnmatchedType(type); + } + else { + result.recordMatchedType(type, typeMatches); + } +} + + + // 注解匹配删除忽略的beanname + for (String annotation : spec.getAnnotations()) { + Set annotationMatches = getBeanNamesForAnnotation(classLoader, beanFactory, annotation, + considerHierarchy); + annotationMatches.removeAll(beansIgnoredByType); + if (annotationMatches.isEmpty()) { + result.recordUnmatchedAnnotation(annotation); + } + else { + result.recordMatchedAnnotation(annotation, annotationMatches); + } + } +``` + +- 在忽略bean找到之后做一个类型移除的操作. + + + +![image-20200825140750035](/images/SpringBoot//image-20200825140750035.png) + + + + + + + +### 返回值 + +- 在返回之前做一堆判断条件. 一旦符合条件这个地方会做一个noMatch的一个对象(`ConditionOutcome`) ,通过返回match对象`ConditionOutcome` + +```java +public static ConditionOutcome noMatch(ConditionMessage message) { + return new ConditionOutcome(false, message); +} +``` + + + +```java + if (!matchResult.isAllMatched()) { + String reason = createOnBeanNoMatchReason(matchResult); + return ConditionOutcome.noMatch(spec.message().because(reason)); + } + // 把注解解析出来获得文本 + matchMessage = spec.message(matchMessage).found("bean", "beans").items(Style.QUOTE, + matchResult.getNamesOfAllMatches()); + } + if (metadata.isAnnotated(ConditionalOnSingleCandidate.class.getName())) { + Spec spec = new SingleCandidateSpec(context, metadata, annotations); + MatchResult matchResult = getMatchingBeans(context, spec); + if (!matchResult.isAllMatched()) { + return ConditionOutcome.noMatch(spec.message().didNotFind("any beans").atAll()); + } + else if (!hasSingleAutowireCandidate(context.getBeanFactory(), matchResult.getNamesOfAllMatches(), + spec.getStrategy() == SearchStrategy.ALL)) { + return ConditionOutcome.noMatch(spec.message().didNotFind("a primary bean from beans") + .items(Style.QUOTE, matchResult.getNamesOfAllMatches())); + } + matchMessage = spec.message(matchMessage).found("a primary bean from beans").items(Style.QUOTE, + matchResult.getNamesOfAllMatches()); + } + if (metadata.isAnnotated(ConditionalOnMissingBean.class.getName())) { + Spec spec = new Spec<>(context, metadata, annotations, + ConditionalOnMissingBean.class); + MatchResult matchResult = getMatchingBeans(context, spec); + if (matchResult.isAnyMatched()) { + String reason = createOnMissingBeanNoMatchReason(matchResult); + return ConditionOutcome.noMatch(spec.message().because(reason)); + } + matchMessage = spec.message(matchMessage).didNotFind("any beans").atAll(); + } + return ConditionOutcome.match(matchMessage); +``` + + + + + + + +![image-20200825141506531](/images/SpringBoot//image-20200825141506531.png) + + + +- 到此结果封装完毕.回到方法`org.springframework.boot.autoconfigure.condition.SpringBootCondition#matches(org.springframework.context.annotation.ConditionContext, org.springframework.core.type.AnnotatedTypeMetadata)` 继续进行 + - 再往后就继续执行spring的bean初始化咯 + + + + + +## MessageSourceAutoConfiguration + + + +- 启动阶段的一个类运行解读 + +- `org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration` + + ```java + @Configuration(proxyBeanMethods = false) + @ConditionalOnMissingBean(name = AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME, search = SearchStrategy.CURRENT) + @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) + @Conditional(ResourceBundleCondition.class) + @EnableConfigurationProperties + public class MessageSourceAutoConfiguration {} + + ``` + + - 根据类的注解信息我们可以找到有`ResourceBundleCondition` + + ![image-20200825092343271](/images/SpringBoot//image-20200825092343271.png) + +- 获取类名或者方法名的结果是`MessageSourceAutoConfiguration`全路径 + +- 继续往下是一个比较的方法(是否符合match) + + `org.springframework.boot.autoconfigure.condition.SpringBootCondition#getMatchOutcome`这个方法是一个抽象方法子类实现 + +- 上图中红框内标注的类为`org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration.ResourceBundleCondition` + + 同时继承`org.springframework.boot.autoconfigure.condition.SpringBootCondition` + + 并且重写了方法`getMatchOutcome` + + ```java + @Override + public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { + // 从 容器中获取 + String basename = context.getEnvironment().getProperty("spring.messages.basename", "messages"); + // 从缓存中获取条件信息 + ConditionOutcome outcome = cache.get(basename); + if (outcome == null) { + // 生成条件信息对象 + outcome = getMatchOutcomeForBasename(context, basename); + // 放入缓存 + cache.put(basename, outcome); + } + return outcome; + } + ``` + + 这个方法主要将比较信息放入, + +- 后续的行为依然是判断是否匹配,匹配就创建. + + + + + + + +## Spring Boot 启动阶段的自动注入 + +```java +org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#filter +``` + + + +```java +private List filter(List configurations, AutoConfigurationMetadata autoConfigurationMetadata) { + long startTime = System.nanoTime(); + String[] candidates = StringUtils.toStringArray(configurations); + boolean[] skip = new boolean[candidates.length]; + boolean skipped = false; + // 获取 AutoConfigurationImportFilter 相关配置 + for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) { + // 执行 aware 相关接口 + invokeAwareMethods(filter); + // 是否可以初始化的结果 + boolean[] match = filter.match(candidates, autoConfigurationMetadata); + for (int i = 0; i < match.length; i++) { + if (!match[i]) { + // 是否跳过 + skip[i] = true; + candidates[i] = null; + skipped = true; + } + } + } + if (!skipped) { + return configurations; + } + List result = new ArrayList<>(candidates.length); + // 处理最终需要的类 + for (int i = 0; i < candidates.length; i++) { + if (!skip[i]) { + result.add(candidates[i]); + } + } + if (logger.isTraceEnabled()) { + int numberFiltered = configurations.size() - result.size(); + logger.trace("Filtered " + numberFiltered + " auto configuration class in " + + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms"); + } + return new ArrayList<>(result); +} +``` + + + +- 在这里有一个关注点 循环方法`getAutoConfigurationImportFilters()` + + + + + +```JAVA +protected List getAutoConfigurationImportFilters() { + return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader); +} +``` + + + +在`spring.factories`文件中找到`AutoConfigurationImportFilter`后面的值 + +```properties +org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\ +org.springframework.boot.autoconfigure.condition.OnBeanCondition,\ +org.springframework.boot.autoconfigure.condition.OnClassCondition,\ +org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition +``` + + + + + +- 此时我们可以和前文的源码分析连接起来有一个完整的认识了 + + ![image-20200825142332485](/images/SpringBoot//image-20200825142332485.png) + + + + + +- 最后来看整体类图 + + ![image-20200825142418115](/images/SpringBoot//image-20200825142418115.png) + diff --git a/docs/nacos/nacos-discovery.md b/docs/nacos/nacos-discovery.md new file mode 100644 index 0000000..75d6b4c --- /dev/null +++ b/docs/nacos/nacos-discovery.md @@ -0,0 +1,859 @@ +# Nacos 服务注册 + +- nacos-spring-boot-project 中有关服务注册的几个项目 + - nacos-discovery-spring-boot-actuator + nacos-discovery-spring-boot-autoconfigure + nacos-discovery-spring-boot-starter + + + + + +```properties +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.alibaba.boot.nacos.discovery.autoconfigure.NacosDiscoveryAutoConfiguration +``` + + + + + +找到注解`NacosDiscoveryAutoConfiguration` + +```java +@ConditionalOnProperty(name = NacosDiscoveryConstants.ENABLED, matchIfMissing = true) +@ConditionalOnMissingBean(name = DISCOVERY_GLOBAL_NACOS_PROPERTIES_BEAN_NAME) +@EnableNacosDiscovery +@EnableConfigurationProperties(value = NacosDiscoveryProperties.class) +@ConditionalOnClass(name = "org.springframework.boot.context.properties.bind.Binder") + public class NacosDiscoveryAutoConfiguration { + + @Bean + public NacosDiscoveryAutoRegister discoveryAutoRegister() { + return new NacosDiscoveryAutoRegister(); + } + +} +``` + + + +- 注解:`EnableNacosDiscovery` + +```java +@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Import(NacosDiscoveryBeanDefinitionRegistrar.class) +public @interface EnableNacosDiscovery {} +``` + +- import 类 :`NacosDiscoveryBeanDefinitionRegistrar` + + + + + +```java +public class NacosDiscoveryBeanDefinitionRegistrar + implements ImportBeanDefinitionRegistrar, EnvironmentAware { + + private Environment environment; + + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, + BeanDefinitionRegistry registry) { + AnnotationAttributes attributes = AnnotationAttributes + .fromMap(importingClassMetadata + .getAnnotationAttributes(EnableNacosDiscovery.class.getName())); + // Register Global Nacos Properties Bean + registerGlobalNacosProperties(attributes, registry, environment, + DISCOVERY_GLOBAL_NACOS_PROPERTIES_BEAN_NAME); + registerGlobalNacosProperties(attributes, registry, environment, + MAINTAIN_GLOBAL_NACOS_PROPERTIES_BEAN_NAME); + // Register Nacos Common Beans + registerNacosCommonBeans(registry); + // Register Nacos Discovery Beans + registerNacosDiscoveryBeans(registry); + } + + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } +} +``` + + + + + +- 两个流程 + + 1. 将注解`EnableNacosDiscovery`的属性读取,放入到 nacos 的全局属性配置中 + + 2. bean 注入 + + + + + + + + + + + +## nacos 全局配置属性 + +- `com.alibaba.nacos.spring.context.annotation.discovery.NacosDiscoveryBeanDefinitionRegistrar#registerBeanDefinitions` + - `com.alibaba.nacos.spring.util.NacosBeanUtils#registerGlobalNacosProperties(org.springframework.core.annotation.AnnotationAttributes, org.springframework.beans.factory.support.BeanDefinitionRegistry, org.springframework.core.env.PropertyResolver, java.lang.String)` + +```java +public static void registerGlobalNacosProperties(AnnotationAttributes attributes, + BeanDefinitionRegistry registry, PropertyResolver propertyResolver, + String beanName) { + if (attributes == null) { + return; // Compatible with null + } + AnnotationAttributes globalPropertiesAttributes = attributes + .getAnnotation("globalProperties"); + registerGlobalNacosProperties((Map) globalPropertiesAttributes, registry, + propertyResolver, beanName); +} +``` + + + +- 贴出注解上的信息 + +```JAVA + NacosProperties globalProperties() default @NacosProperties(username = USERNAME_PLACEHOLDER, password = PASSWORD_PLACEHOLDER, endpoint = ENDPOINT_PLACEHOLDER, namespace = NAMESPACE_PLACEHOLDER, accessKey = ACCESS_KEY_PLACEHOLDER, secretKey = SECRET_KEY_PLACEHOLDER, serverAddr = SERVER_ADDR_PLACEHOLDER, contextPath = CONTEXT_PATH_PLACEHOLDER, clusterName = CLUSTER_NAME_PLACEHOLDER, encode = ENCODE_PLACEHOLDER); + +``` + + + + + +- 通过下面这段代码会将注解信息获取到对象`AnnotationAttributes globalPropertiesAttributes`中 + + ```java + AnnotationAttributes globalPropertiesAttributes = attributes + .getAnnotation("globalProperties"); + ``` + + + +- 下一段代码是将属性换算出来 + + ```java + registerGlobalNacosProperties((Map) globalPropertiesAttributes, registry, + propertyResolver, beanName) + + + public static void registerGlobalNacosProperties(Map globalPropertiesAttributes, + BeanDefinitionRegistry registry, PropertyResolver propertyResolver, + String beanName) { + // 占位符解析成具体的配置信息 + Properties globalProperties = resolveProperties(globalPropertiesAttributes, + propertyResolver); + // 单例注册 + registerSingleton(registry, beanName, globalProperties); + } + + ``` + +![image-20200821111938485](/images/nacos/image-20200821111938485.png) + + + + + + + + + +## registerNacosCommonBeans + +``` +public static void registerNacosCommonBeans(BeanDefinitionRegistry registry) { + // Register NacosApplicationContextHolder Bean + registerNacosApplicationContextHolder(registry); + // Register AnnotationNacosInjectedBeanPostProcessor Bean + registerAnnotationNacosInjectedBeanPostProcessor(registry); +} +``` + + + + + +- 主要方法: registerInfrastructureBean + 1. 定义出bean + 2. 设置构造参数 + 3. 注册对象 + +```java +public static void registerInfrastructureBean(BeanDefinitionRegistry registry, + String beanName, Class beanClass, Object... constructorArgs) { + // Build a BeanDefinition for NacosServiceFactory class + // 定义出 bean 根据类型 + BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder + .rootBeanDefinition(beanClass); + for (Object constructorArg : constructorArgs) { + beanDefinitionBuilder.addConstructorArgValue(constructorArg); + } + // ROLE_INFRASTRUCTURE + beanDefinitionBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + // Register + registry.registerBeanDefinition(beanName, + beanDefinitionBuilder.getBeanDefinition()); +} +``` + + + + + + + +## @EnableConfigurationProperties(value = NacosDiscoveryProperties.class) + +属性读取,从application配置文件中读取数据转换成java对象。 + +![image-20200821132413628](/images/nacos/image-20200821132413628.png) + + + + + +## NacosDiscoveryAutoRegister + + + +```java +public class NacosDiscoveryAutoRegister + implements ApplicationListener {} +``` + +- 处理一个`WebServerInitializedEvent` 事件的方法 + + + +- 重写方法如下,主要工作内容 + 1. 把服务发现配置读取出来 + 2. 设置一些数据值 + 3. 调用服务注册接口 + + + +```java +@Override +public void onApplicationEvent(WebServerInitializedEvent event) { + + if (!discoveryProperties.isAutoRegister()) { + return; + } + + Register register = discoveryProperties.getRegister(); + + if (StringUtils.isEmpty(register.getIp())) { + register.setIp(NetUtils.localIP()); + } + + if (register.getPort() == 0) { + register.setPort(event.getWebServer().getPort()); + } + + register.getMetadata().put("preserved.register.source", "SPRING_BOOT"); + + register.setInstanceId(""); + + String serviceName = register.getServiceName(); + + if (StringUtils.isEmpty(serviceName)){ + if (StringUtils.isEmpty(applicationName)){ + throw new AutoRegisterException("serviceName notNull"); + } + serviceName = applicationName; + } + + try { + namingService.registerInstance(serviceName, register.getGroupName(), + register); + logger.info("Finished auto register service : {}, ip : {}, port : {}", + serviceName, register.getIp(), register.getPort()); + } catch (NacosException e) { + throw new AutoRegisterException(e); + } +} +``` + + + +- 注册的参数 + + ![image-20200821133350982](/images/nacos/image-20200821133350982.png) + + + + + +## 服务注册 + +![image-20200821133445090](/images/nacos/image-20200821133445090.png) + + + +- 注册一个实例 + 1. 将 instance 对象转换成 BeatInfo 对象 + 2. 注册实例 + +```java + @Override + public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException { + + if (instance.isEphemeral()) { + // 实例信息转换 + BeatInfo beatInfo = new BeatInfo(); + beatInfo.setServiceName(NamingUtils.getGroupedName(serviceName, groupName)); + beatInfo.setIp(instance.getIp()); + beatInfo.setPort(instance.getPort()); + beatInfo.setCluster(instance.getClusterName()); + beatInfo.setWeight(instance.getWeight()); + beatInfo.setMetadata(instance.getMetadata()); + beatInfo.setScheduled(false); + beatInfo.setPeriod(instance.getInstanceHeartBeatInterval()); + // 插入这条实例的信息 + beatReactor.addBeatInfo(NamingUtils.getGroupedName(serviceName, groupName), + beatInfo); + } + + serverProxy.registerService(NamingUtils.getGroupedName(serviceName, groupName), groupName, instance); + } + +``` + + + + + +- addBeatInfo + - 创建了一个定时任务 BeatTask + +```java +public void addBeatInfo(String serviceName, BeatInfo beatInfo) { + NAMING_LOGGER.info("[BEAT] adding beat: {} to beat map.", beatInfo); + String key = buildKey(serviceName, beatInfo.getIp(), beatInfo.getPort()); + BeatInfo existBeat = null; + //fix #1733 + if ((existBeat = dom2Beat.remove(key)) != null) { + existBeat.setStopped(true); + } + dom2Beat.put(key, beatInfo); + executorService.schedule(new BeatTask(beatInfo), beatInfo.getPeriod(), TimeUnit.MILLISECONDS); + MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size()); +} +``` + + + +### BeatTask + +``` +class BeatTask implements Runnable { + + BeatInfo beatInfo; + + public BeatTask(BeatInfo beatInfo) { + this.beatInfo = beatInfo; + } + + @Override + public void run() { + if (beatInfo.isStopped()) { + return; + } + long nextTime = beatInfo.getPeriod(); + try { + // 与nacos进行一次rest请求交互 + JSONObject result = serverProxy.sendBeat(beatInfo, BeatReactor.this.lightBeatEnabled); + long interval = result.getIntValue("clientBeatInterval"); + boolean lightBeatEnabled = false; + if (result.containsKey(CommonParams.LIGHT_BEAT_ENABLED)) { + lightBeatEnabled = result.getBooleanValue(CommonParams.LIGHT_BEAT_ENABLED); + } + BeatReactor.this.lightBeatEnabled = lightBeatEnabled; + if (interval > 0) { + nextTime = interval; + } + int code = NamingResponseCode.OK; + if (result.containsKey(CommonParams.CODE)) { + code = result.getIntValue(CommonParams.CODE); + } + // 如果nacos找不到当前实例, + if (code == NamingResponseCode.RESOURCE_NOT_FOUND) { + Instance instance = new Instance(); + instance.setPort(beatInfo.getPort()); + instance.setIp(beatInfo.getIp()); + instance.setWeight(beatInfo.getWeight()); + instance.setMetadata(beatInfo.getMetadata()); + instance.setClusterName(beatInfo.getCluster()); + instance.setServiceName(beatInfo.getServiceName()); + instance.setInstanceId(instance.getInstanceId()); + instance.setEphemeral(true); + try { + // 执行注册服务 + serverProxy.registerService(beatInfo.getServiceName(), + NamingUtils.getGroupName(beatInfo.getServiceName()), instance); + } catch (Exception ignore) { + } + } + } catch (NacosException ne) { + NAMING_LOGGER.error("[CLIENT-BEAT] failed to send beat: {}, code: {}, msg: {}", + JSON.toJSONString(beatInfo), ne.getErrCode(), ne.getErrMsg()); + + } + executorService.schedule(new BeatTask(beatInfo), nextTime, TimeUnit.MILLISECONDS); + } +} +``` + +- 定时任务说明 + 1. 和nacos进行一次交互,根据交互结果的code判断,如果不在nacos会执行注册. + + + + + +- 发送请求的方法 + + ```java + public String reqAPI(String api, Map params, String body, List servers, String method) throws NacosException { + + params.put(CommonParams.NAMESPACE_ID, getNamespaceId()); + + if (CollectionUtils.isEmpty(servers) && StringUtils.isEmpty(nacosDomain)) { + throw new NacosException(NacosException.INVALID_PARAM, "no server available"); + } + + NacosException exception = new NacosException(); + + if (servers != null && !servers.isEmpty()) { + + Random random = new Random(System.currentTimeMillis()); + int index = random.nextInt(servers.size()); + + for (int i = 0; i < servers.size(); i++) { + // 获取nacos所在的ip+port地址 + String server = servers.get(index); + try { + // 进行请求 + return callServer(api, params, body, server, method); + } catch (NacosException e) { + exception = e; + if (NAMING_LOGGER.isDebugEnabled()) { + NAMING_LOGGER.debug("request {} failed.", server, e); + } + } + index = (index + 1) % servers.size(); + } + } + + if (StringUtils.isNotBlank(nacosDomain)) { + for (int i = 0; i < UtilAndComs.REQUEST_DOMAIN_RETRY_COUNT; i++) { + try { + return callServer(api, params, body, nacosDomain, method); + } catch (NacosException e) { + exception = e; + if (NAMING_LOGGER.isDebugEnabled()) { + NAMING_LOGGER.debug("request {} failed.", nacosDomain, e); + } + } + } + } + + NAMING_LOGGER.error("request: {} failed, servers: {}, code: {}, msg: {}", + api, servers, exception.getErrCode(), exception.getErrMsg()); + + throw new NacosException(exception.getErrCode(), "failed to req API:/api/" + api + " after all servers(" + servers + ") tried: " + + exception.getMessage()); + + } + ``` + + + + + +**学习点** + +- 这里采用随机值作为第一个server的获取,主要目的是为了将请求随机分配给不同的nacos服务 + + 如果直接使用for循环的索引那第一台nacos服务会收到所有的请求,直到这台服务坏了才会请求第二台 + + Random random = new Random(System.currentTimeMillis()); + int index = random.nextInt(servers.size()); + + for (int i = 0; i < servers.size(); i++) { + // 获取nacos所在的ip+port地址 + String server = servers.get(index); + try { + // 进行请求 + return callServer(api, params, body, server, method); + } catch (NacosException e) { + exception = e; + if (NAMING_LOGGER.isDebugEnabled()) { + NAMING_LOGGER.debug("request {} failed.", server, e); + } + } + index = (index + 1) % servers.size(); + } + } + + + + + + +### registerService + +- 注册方法就是请求一次接口,将数据发送给nacos就完成了 + +```java +public void registerService(String serviceName, String groupName, Instance instance) throws NacosException { + + NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}", + namespaceId, serviceName, instance); + + final Map params = new HashMap(9); + params.put(CommonParams.NAMESPACE_ID, namespaceId); + params.put(CommonParams.SERVICE_NAME, serviceName); + params.put(CommonParams.GROUP_NAME, groupName); + params.put(CommonParams.CLUSTER_NAME, instance.getClusterName()); + params.put("ip", instance.getIp()); + params.put("port", String.valueOf(instance.getPort())); + params.put("weight", String.valueOf(instance.getWeight())); + params.put("enable", String.valueOf(instance.isEnabled())); + params.put("healthy", String.valueOf(instance.isHealthy())); + params.put("ephemeral", String.valueOf(instance.isEphemeral())); + params.put("metadata", JSON.toJSONString(instance.getMetadata())); + + reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, HttpMethod.POST); + +} +``` + + + + + + + +- 服务注册的接口 + - `/nacos/v1/ns/instance` + - `/nacos/v1/ns/instance/beat` + + + +- 接下来去寻找这两个接口的实现 + + `com.alibaba.nacos.naming.controllers.InstanceController` + + + + + + + +## nacos 服务端 + +### 实例注册 + + + +```java +public void registerInstance(String namespaceId, String serviceName, Instance instance) throws NacosException { + // 创建空服务 + createEmptyService(namespaceId, serviceName, instance.isEphemeral()); + + Service service = getService(namespaceId, serviceName); + + if (service == null) { + throw new NacosException(NacosException.INVALID_PARAM, + "service not found, namespace: " + namespaceId + ", service: " + serviceName); + } + + addInstance(namespaceId, serviceName, instance.isEphemeral(), instance); +} +``` + + + +- 创建空服务的流程 + + - 获取服务对象 + + nacos 的服务信息存储在 + + `com.alibaba.nacos.naming.core.ServiceManager#serviceMap` + + ```java + private Map> serviceMap = new ConcurrentHashMap<>(); + ``` + +```java +public void createServiceIfAbsent(String namespaceId, String serviceName, boolean local, Cluster cluster) throws NacosException { + // 获取服务信息 + Service service = getService(namespaceId, serviceName); + if (service == null) { + + Loggers.SRV_LOG.info("creating empty service {}:{}", namespaceId, serviceName); + service = new Service(); + service.setName(serviceName); + service.setNamespaceId(namespaceId); + service.setGroupName(NamingUtils.getGroupName(serviceName)); + // now validate the service. if failed, exception will be thrown + service.setLastModifiedMillis(System.currentTimeMillis()); + service.recalculateChecksum(); + if (cluster != null) { + cluster.setService(service); + service.getClusterMap().put(cluster.getName(), cluster); + } + service.validate(); + + putServiceAndInit(service); + if (!local) { + addOrReplaceService(service); + } + } +} +``` + + + +- 在了解map结构后不难理解下面这个获取Service的方法了 + +```JAVA +public Service getService(String namespaceId, String serviceName) { + if (serviceMap.get(namespaceId) == null) { + return null; + } + return chooseServiceMap(namespaceId).get(serviceName); +} +``` + + + + + +```java +private void putServiceAndInit(Service service) throws NacosException { + putService(service); + service.init(); + consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), true), service); + consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), false), service); + Loggers.SRV_LOG.info("[NEW-SERVICE] {}", service.toJSON()); +} +``` + + + +- 把服务加入map对象 + +```java +public void putService(Service service) { + if (!serviceMap.containsKey(service.getNamespaceId())) { + synchronized (putServiceLock) { + if (!serviceMap.containsKey(service.getNamespaceId())) { + serviceMap.put(service.getNamespaceId(), new ConcurrentHashMap<>(16)); + } + } + } + serviceMap.get(service.getNamespaceId()).put(service.getName(), service); +} +``` + + + +- init 方法设置了一个数据验证的任务 , 并且在集群中设置service信息 + +```java +public void init() { + + HealthCheckReactor.scheduleCheck(clientBeatCheckTask); + + for (Map.Entry entry : clusterMap.entrySet()) { + entry.getValue().setService(this); + entry.getValue().init(); + } +} +``` + +- 再往后添加两个key的监听 + + + +- addInstance 方法 + +```java +public void addInstance(String namespaceId, String serviceName, boolean ephemeral, Instance... ips) throws NacosException { + + String key = KeyBuilder.buildInstanceListKey(namespaceId, serviceName, ephemeral); + + Service service = getService(namespaceId, serviceName); + + synchronized (service) { + List instanceList = addIpAddresses(service, ephemeral, ips); + + Instances instances = new Instances(); + instances.setInstanceList(instanceList); + + consistencyService.put(key, instances); + } +} +``` + + + + + +- 简单理解 consistencyService 结构信息 + - key: 定义的一个名字 + - value : 实例的列表 + + + + + + +### 实例健康检查 + +- 获取实例独享, 从 service 中根据集群名称获取实例列表 , 再根据ip + 端口 返回实例对象 + +```java +Instance instance = serviceManager.getInstance(namespaceId, serviceName, clusterName, ip, port); +``` + + + +```java +public Instance getInstance(String namespaceId, String serviceName, String cluster, String ip, int port) { + Service service = getService(namespaceId, serviceName); + if (service == null) { + return null; + } + + List clusters = new ArrayList<>(); + clusters.add(cluster); + + List ips = service.allIPs(clusters); + if (ips == null || ips.isEmpty()) { + return null; + } + + for (Instance instance : ips) { + if (instance.getIp().equals(ip) && instance.getPort() == port) { + return instance; + } + } + + return null; +} +``` + + + + + + + +- 实例健康检查接口做的事件 + 1. 获取实例 + 1. 实例不存在注册实例 + 2. 获取服务 + 1. 服务不存在抛出异常 + 2. 服务存在执行一个心跳方法 + 3. 组装结果返回 + + + + + +```java +@CanDistro +@PutMapping("/beat") +@Secured(parser = NamingResourceParser.class, action = ActionTypes.WRITE) +public JSONObject beat(HttpServletRequest request) throws Exception { + + JSONObject result = new JSONObject(); + + result.put("clientBeatInterval", switchDomain.getClientBeatInterval()); + String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME); + String namespaceId = WebUtils.optional(request, CommonParams.NAMESPACE_ID, + Constants.DEFAULT_NAMESPACE_ID); + String clusterName = WebUtils.optional(request, CommonParams.CLUSTER_NAME, + UtilsAndCommons.DEFAULT_CLUSTER_NAME); + String ip = WebUtils.optional(request, "ip", StringUtils.EMPTY); + int port = Integer.parseInt(WebUtils.optional(request, "port", "0")); + String beat = WebUtils.optional(request, "beat", StringUtils.EMPTY); + + RsInfo clientBeat = null; + if (StringUtils.isNotBlank(beat)) { + clientBeat = JSON.parseObject(beat, RsInfo.class); + } + + if (clientBeat != null) { + if (StringUtils.isNotBlank(clientBeat.getCluster())) { + clusterName = clientBeat.getCluster(); + } + ip = clientBeat.getIp(); + port = clientBeat.getPort(); + } + + if (Loggers.SRV_LOG.isDebugEnabled()) { + Loggers.SRV_LOG.debug("[CLIENT-BEAT] full arguments: beat: {}, serviceName: {}", clientBeat, serviceName); + } + // 获取实例 + Instance instance = serviceManager.getInstance(namespaceId, serviceName, clusterName, ip, port); + + if (instance == null) { + if (clientBeat == null) { + result.put(CommonParams.CODE, NamingResponseCode.RESOURCE_NOT_FOUND); + return result; + } + instance = new Instance(); + instance.setPort(clientBeat.getPort()); + instance.setIp(clientBeat.getIp()); + instance.setWeight(clientBeat.getWeight()); + instance.setMetadata(clientBeat.getMetadata()); + instance.setClusterName(clusterName); + instance.setServiceName(serviceName); + instance.setInstanceId(instance.getInstanceId()); + instance.setEphemeral(clientBeat.isEphemeral()); + + serviceManager.registerInstance(namespaceId, serviceName, instance); + } + + Service service = serviceManager.getService(namespaceId, serviceName); + + if (service == null) { + throw new NacosException(NacosException.SERVER_ERROR, + "service not found: " + serviceName + "@" + namespaceId); + } + if (clientBeat == null) { + clientBeat = new RsInfo(); + clientBeat.setIp(ip); + clientBeat.setPort(port); + clientBeat.setCluster(clusterName); + } + // 处理心跳方法 + service.processClientBeat(clientBeat); + + result.put(CommonParams.CODE, NamingResponseCode.OK); + result.put("clientBeatInterval", instance.getInstanceHeartBeatInterval()); + result.put(SwitchEntry.LIGHT_BEAT_ENABLED, switchDomain.isLightBeatEnabled()); + return result; +} +``` \ No newline at end of file diff --git a/images/SpringBoot/image-20200601170659521.png b/images/SpringBoot/image-20200601170659521.png new file mode 100644 index 0000000..15b3462 Binary files /dev/null and b/images/SpringBoot/image-20200601170659521.png differ diff --git a/images/SpringBoot/image-20200824085726621.png b/images/SpringBoot/image-20200824085726621.png new file mode 100644 index 0000000..26d75ea Binary files /dev/null and b/images/SpringBoot/image-20200824085726621.png differ diff --git a/images/SpringBoot/image-20200825084844709.png b/images/SpringBoot/image-20200825084844709.png new file mode 100644 index 0000000..700597a Binary files /dev/null and b/images/SpringBoot/image-20200825084844709.png differ diff --git a/images/SpringBoot/image-20200825092343271.png b/images/SpringBoot/image-20200825092343271.png new file mode 100644 index 0000000..9d5289e Binary files /dev/null and b/images/SpringBoot/image-20200825092343271.png differ diff --git a/images/SpringBoot/image-20200825140750035.png b/images/SpringBoot/image-20200825140750035.png new file mode 100644 index 0000000..f24f1ce Binary files /dev/null and b/images/SpringBoot/image-20200825140750035.png differ diff --git a/images/SpringBoot/image-20200825141506531.png b/images/SpringBoot/image-20200825141506531.png new file mode 100644 index 0000000..061160a Binary files /dev/null and b/images/SpringBoot/image-20200825141506531.png differ diff --git a/images/SpringBoot/image-20200825142332485.png b/images/SpringBoot/image-20200825142332485.png new file mode 100644 index 0000000..6d1e4bd Binary files /dev/null and b/images/SpringBoot/image-20200825142332485.png differ diff --git a/images/SpringBoot/image-20200825142418115.png b/images/SpringBoot/image-20200825142418115.png new file mode 100644 index 0000000..64261d4 Binary files /dev/null and b/images/SpringBoot/image-20200825142418115.png differ diff --git a/images/nacos/image-20200821111938485.png b/images/nacos/image-20200821111938485.png new file mode 100644 index 0000000..ff27ea0 Binary files /dev/null and b/images/nacos/image-20200821111938485.png differ diff --git a/images/nacos/image-20200821132413628.png b/images/nacos/image-20200821132413628.png new file mode 100644 index 0000000..22725bd Binary files /dev/null and b/images/nacos/image-20200821132413628.png differ diff --git a/images/nacos/image-20200821133350982.png b/images/nacos/image-20200821133350982.png new file mode 100644 index 0000000..23a74f7 Binary files /dev/null and b/images/nacos/image-20200821133350982.png differ diff --git a/images/nacos/image-20200821133445090.png b/images/nacos/image-20200821133445090.png new file mode 100644 index 0000000..9d59fdd Binary files /dev/null and b/images/nacos/image-20200821133445090.png differ diff --git a/images/spring/BeanFactory.png b/images/spring/BeanFactory.png new file mode 100644 index 0000000..9731ad1 Binary files /dev/null and b/images/spring/BeanFactory.png differ diff --git a/images/spring/RootBeanDefinition.png b/images/spring/RootBeanDefinition.png new file mode 100644 index 0000000..76358c4 Binary files /dev/null and b/images/spring/RootBeanDefinition.png differ diff --git a/images/spring/TemplateAwareExpressionParser.png b/images/spring/TemplateAwareExpressionParser.png new file mode 100644 index 0000000..954a266 Binary files /dev/null and b/images/spring/TemplateAwareExpressionParser.png differ diff --git a/images/spring/image-20200824094154847.png b/images/spring/image-20200824094154847.png new file mode 100644 index 0000000..c6c2d6a Binary files /dev/null and b/images/spring/image-20200824094154847.png differ diff --git a/images/spring/image-20200824104529315.png b/images/spring/image-20200824104529315.png new file mode 100644 index 0000000..67ea81b Binary files /dev/null and b/images/spring/image-20200824104529315.png differ diff --git a/images/spring/image-20200902102912716.png b/images/spring/image-20200902102912716.png new file mode 100644 index 0000000..090b14c Binary files /dev/null and b/images/spring/image-20200902102912716.png differ diff --git a/images/spring/image-20200902103154580.png b/images/spring/image-20200902103154580.png new file mode 100644 index 0000000..40a6646 Binary files /dev/null and b/images/spring/image-20200902103154580.png differ diff --git a/images/spring/image-20200902105454958.png b/images/spring/image-20200902105454958.png new file mode 100644 index 0000000..003c83f Binary files /dev/null and b/images/spring/image-20200902105454958.png differ diff --git a/images/spring/image-20200903091759451.png b/images/spring/image-20200903091759451.png new file mode 100644 index 0000000..23acc2f Binary files /dev/null and b/images/spring/image-20200903091759451.png differ diff --git a/images/spring/image-20200903111128603.png b/images/spring/image-20200903111128603.png new file mode 100644 index 0000000..f1f8474 Binary files /dev/null and b/images/spring/image-20200903111128603.png differ diff --git a/images/spring/image-20200903150738285.png b/images/spring/image-20200903150738285.png new file mode 100644 index 0000000..bc8c000 Binary files /dev/null and b/images/spring/image-20200903150738285.png differ diff --git a/images/spring/image-20200903150930186.png b/images/spring/image-20200903150930186.png new file mode 100644 index 0000000..5c33bb2 Binary files /dev/null and b/images/spring/image-20200903150930186.png differ diff --git a/images/spring/image-20200903153057321.png b/images/spring/image-20200903153057321.png new file mode 100644 index 0000000..d4c4053 Binary files /dev/null and b/images/spring/image-20200903153057321.png differ diff --git a/images/spring/image-20200903153432559.png b/images/spring/image-20200903153432559.png new file mode 100644 index 0000000..61f6496 Binary files /dev/null and b/images/spring/image-20200903153432559.png differ diff --git a/images/spring/image-20200903153533141.png b/images/spring/image-20200903153533141.png new file mode 100644 index 0000000..005386d Binary files /dev/null and b/images/spring/image-20200903153533141.png differ diff --git a/images/spring/image-20200903153617353.png b/images/spring/image-20200903153617353.png new file mode 100644 index 0000000..98d0711 Binary files /dev/null and b/images/spring/image-20200903153617353.png differ