Spring源码分析(BeanDefinition)

news2024/11/25 3:29:46

文章目录

  • Spring源码分析(BeanDefinition)
  • 一、概述
    • 1、BeanDefinition 的理解
    • 2、BeanDefinition 接口
    • 3、BeanDefinition 的实现
    • 4、BeanDefinitionHolder 类
  • 二、BeanDefinition 的加载
    • 1、reader 的获取
      • 1)registerAnnotationConfigProcessors
      • 2)registerPostProcessor
    • 2、reader.register
    • 3、scanner 的获取
    • 4、scanner.scan
    • 5、@Scope 的 proxyMode
      • 1)@Scope
      • 2)@Scope 的解析
      • 3)applyScopedProxyMode
      • 4)ScopedProxyFactoryBean
      • 5)小结
  • 三、BeanDefinition 的注册
    • 1、registerBeanDefinition
    • 2、registerAlias

Spring源码分析(BeanDefinition)

一、概述

1、BeanDefinition 的理解

BeanDefinition 类似于 Java 中的 Class,Class 是创建对象的模板,而 BeanDefinition 就是创建生成 Bean的模板。

BeanDefinition 生成 Bean 实例,Bean实例交给 BeanFactory 管理,BeanFactory 交给 ApplicationContext 提供基础服务。

在这里插入图片描述

2、BeanDefinition 接口

BeanDefinition 中保存了 Bean 的信息(Bean 在代码层面上可以简单认为是 BeanDefinition 的实例)

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

    // Bean的作用域:默认只提供 sington 和 prototype 两种
    // web扩展的作用域:request, session, globalSession, application, websocket
    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;	// 单例
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;	// 原型(多例)

    // 设置Bean的作用域
    void setScope(@Nullable String scope);   
    @Nullable
    String getScope();

    // 三个角色类型
    int ROLE_APPLICATION = 0;		// 表示这个 Bean 是用户自己定义的 Bean
    int ROLE_SUPPORT = 1;			// 表示这个 Bean 是某些复杂配置的支撑部分
    int ROLE_INFRASTRUCTURE = 2;	// 表示这个 Bean 是 Spring 内部的 Bean

    // 设置角色类型
    void setRole(int role);
    int getRole();

    
    // Modifiable attributes

    
	// 设置父 Bean(这里是 bean 继承,不是 java 继承)
    void setParentName(@Nullable String parentName); 
    @Nullable
    String getParentName();

    // 设置 Bean 的类名称(将来是要通过反射来生成实例的)
    void setBeanClassName(@Nullable String beanClassName);    
    @Nullable
    String getBeanClassName();

	// 设置是否懒加载	<bean lazy-init="">
    void setLazyInit(boolean lazyInit);
    boolean isLazyInit();

    // 依赖的bean列表 <bean depends-on=""> @DependsOn
    void setDependsOn(@Nullable String... dependsOn);
    @Nullable
    String[] getDependsOn();

    // 设置该 Bean 是否可以注入到其他 Bean 中
    // 只对根据类型注入有效,如果根据名称注入,即使这边设置了 false,也是可以的
    void setAutowireCandidate(boolean autowireCandidate);
    boolean isAutowireCandidate();

	// 同一接口的多个实现,如果不指定名字的话,Spring 会优先选择设置 primary 为 true 的 bean
    void setPrimary(boolean primary);
    boolean isPrimary();

    // 如果该 Bean 采用工厂方法生成,指定工厂名称。
    void setFactoryBeanName(@Nullable String factoryBeanName);
    @Nullable
    String getFactoryBeanName();

    // 指定工厂类中的 工厂方法名称
    void setFactoryMethodName(@Nullable String factoryMethodName);
    @Nullable
    String getFactoryMethodName();

    /**
	 * Bean 构造方法的参数,用于实例化 Bean 判断
	 */
    ConstructorArgumentValues getConstructorArgumentValues();
    default boolean hasConstructorArgumentValues() {
        return !getConstructorArgumentValues().isEmpty();
    }

    /**
	 * Bean 中的属性值
	 */
    MutablePropertyValues getPropertyValues();
    default boolean hasPropertyValues() {
        return !getPropertyValues().isEmpty();
    }

    /**
	 * Bean 初始化方法 @Bean(initMethod="init") 来指定初始化方法 类似 @PostConstruct
	 */
    void setInitMethodName(@Nullable String initMethodName);
    @Nullable
    String getInitMethodName();

    /**
	 * Bean 销毁方法  @Bean(destroyMethod = "") 类似 @PreDestory
	 */
    void setDestroyMethodName(@Nullable String destroyMethodName);
    @Nullable
    String getDestroyMethodName();

    /**
	 * Bean 描述信息
	 */
    void setDescription(@Nullable String description);
    @Nullable
    String getDescription();

    
    // Read-only attributes
    
    
    // 返回此bean定义的可解析类型
    ResolvableType getResolvableType();

    boolean isSingleton();
    boolean isPrototype();

    boolean isAbstract();

    @Nullable
    String getResourceDescription();

    @Nullable
    BeanDefinition getOriginatingBeanDefinition();

}

3、BeanDefinition 的实现

在这里插入图片描述

主要分为 以 AnnotatedBeanDefinition 为首的 注解派 和 以 AbstractBeanDefinition 为首的 常规派。

  • @Controller、@Service、@Mapper 什么的都包装成了 ScannedGenericBeanDefinition
  • @Configuration 以及 一些自动装配类 都包装成了 AnnotatedGenericBeanDefinition
  • @Configuration 里的 @Bean 都包装成了 ConfigurationClassBeanDefinition

4、BeanDefinitionHolder 类

public class BeanDefinitionHolder implements BeanMetadataElement {

    // bean的定义
    private final BeanDefinition beanDefinition;

    // bean的名称
    private final String beanName;

    // bean的别名
    private final String[] aliases;
    
    //...
}

二、BeanDefinition 的加载

通过 AbstractRefreshableApplicationContextloadBeanDefinitions 方法 加载 BeanDefinition

// org.springframework.context.support.AbstractRefreshableApplicationContext

protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
    throws BeansException, IOException;

这里我们主要看 AnnotationConfigWebApplicationContext 中的实现

// org.springframework.web.context.support.AnnotationConfigWebApplicationContext

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {    
    // reader 用于处理注解的bean定义
    AnnotatedBeanDefinitionReader reader = this.getAnnotatedBeanDefinitionReader(beanFactory);
    // scanner 用于扫描类路径下的bean定义
    ClassPathBeanDefinitionScanner scanner = this.getClassPathBeanDefinitionScanner(beanFactory);

    // 获取BeanName生成器
    BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
    if (beanNameGenerator != null) {
        // 设置到reader和scanner
        reader.setBeanNameGenerator(beanNameGenerator);
        scanner.setBeanNameGenerator(beanNameGenerator);
        // 注册为单例bean(internalConfigurationBeanNameGenerator)
        beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
    }

    // 获取Scope解析器
    ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
    if (scopeMetadataResolver != null) {
        // 设置到reader和scanner
        reader.setScopeMetadataResolver(scopeMetadataResolver);
        scanner.setScopeMetadataResolver(scopeMetadataResolver);
    }

    // 注册组件bean
    if (!this.componentClasses.isEmpty()) {
        // ...
        reader.register(ClassUtils.toClassArray(this.componentClasses));
    }

    // 扫描并注册基础包路径下的bean
    if (!this.basePackages.isEmpty()) {
        // ...
        scanner.scan(StringUtils.toStringArray(this.basePackages));
    }

    // 获取存放了 BeanDefinition 的资源路径
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
        // 从配置位置加载 BeanDefinition
        for (String configLocation : configLocations) {
            try {
                // 使用 当前容器的类加载器 加载指定路径的字节码类文件
                Class<?> clazz = ClassUtils.forName(configLocation, getClassLoader());
                if (logger.isTraceEnabled()) {
                    logger.trace("Registering [" + configLocation + "]");
                }
                // 注册加载的clazz
                reader.register(clazz);
            } 
            catch (ClassNotFoundException ex) {
                // logger...
                
                // 如果类加载器加载失败,则改用scanner扫描给定路径包及其子包中的类
                int count = scanner.scan(configLocation);
                if (count == 0 && logger.isDebugEnabled()) {
                    // logger...
                }
            }
        }
    }
}

可以看到,BeanDefinition的注册主要由 readerscanner 完成:

  • 通过 AnnotatedBeanDefinitionReaderregister 方法,注册组件Bean。
  • 通过 ClassPathBeanDefinitionScannerscan 方法,扫描并注册指定路径下的Bean。

这两个都用于注册 BeanDefinition,两个类功能整体上类似。

1、reader 的获取

// org.springframework.web.context.support.AnnotationConfigWebApplicationContext

protected AnnotatedBeanDefinitionReader getAnnotatedBeanDefinitionReader(DefaultListableBeanFactory beanFactory) {
    return new AnnotatedBeanDefinitionReader(beanFactory, getEnvironment());
}
// org.springframework.context.annotation.AnnotatedBeanDefinitionReader

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    Assert.notNull(environment, "Environment must not be null");
    this.registry = registry;
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    // 注册相关处理器
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

从上面的代码可知,实例化AnnotatedBeanDefinitionReader时,会注册相关的处理器:

类名称说明
ConfigurationClassPostProcessor处理@Configuration注解
AutowiredAnnotationBeanPostProcessor处理@Autowired@Value注解
RequiredAnnotationBeanPostProcessor处理@Required注解
CommonAnnotationBeanPostProcessor处理@Resource注解
EventListenerMethodProcessor处理@EventListener注解
DefaultEventListenerFactory处理@EventListener注解

PS:scanner.scan 也有 registerAnnotationConfigProcessors 这块逻辑。

1)registerAnnotationConfigProcessors

下面看一下代码:

// org.springframework.context.annotation.AnnotationConfigUtils

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
    registerAnnotationConfigProcessors(registry, null);
}

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
    BeanDefinitionRegistry registry, @Nullable Object source) {

    // 获取beanFactory
    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);

    if (beanFactory != null) {
        // 设置 AnnotationAwareOrderComparator 作为依赖比较器
        // 为了处理 @Order 注解
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        // 设置 ContextAnnotationAutowireCandidateResolver 作为自动装配候选解析器
        // 为了自动装配时能够正确地处理 @Autowired 和 @Qualifier 注解,以及其他相关的上下文注解。
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

    // internalConfigurationAnnotationProcessor(内部管理 Configuration 注解处理器 的 bean 的名称)
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        // ConfigurationClassPostProcessor(处理 @Configuration 类)
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // internalAutowiredAnnotationProcessor(内部管理 Autowired 注解处理器 的 bean 的名称)
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        // AutowiredAnnotationBeanPostProcessor(处理 @Autowired、@Value等)
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // internalCommonAnnotationProcessor(内部管理 JSR-250 注解处理器 的 bean 的名称)
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        // CommonAnnotationBeanPostProcessor(处理 @Resource、@PostConstruct、@PreDestroy等)
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // internalPersistenceAnnotationProcessor(内部管理  JPA 注解处理器 的 bean 的名称)
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition();
        try {
            // PersistenceAnnotationBeanPostProcessor(处理SpringJPA相关)
            def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                                                AnnotationConfigUtils.class.getClassLoader()));
        }
        catch (ClassNotFoundException ex) {...}
        def.setSource(source);
        // internalPersistenceAnnotationProcessor
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // internalEventListenerProcessor(内部管理 @EventListener 注解 处理器 的 bean 的名称)
    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
        // EventListenerMethodProcessor(处理 @EventListener)
        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }

    // internalEventListenerFactory(内部管理 EventListenerFactory 的 bean 的名称)
    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
        // DefaultEventListenerFactory(处理 @EventListener)
        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
}

2)registerPostProcessor

// org.springframework.context.annotation.AnnotationConfigUtils

private static BeanDefinitionHolder registerPostProcessor(
    BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

    // 表明这个 Bean 是 Spring 内部的 Bean
    definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

    // 注册相关处理器的BeanDefinition
    registry.registerBeanDefinition(beanName, definition);

    // 返回 BeanDefinitionHolder
    return new BeanDefinitionHolder(definition, beanName);
}

2、reader.register

// org.springframework.context.annotation.AnnotatedBeanDefinitionReader

public void register(Class<?>... componentClasses) {
    // 遍历注册每一个组件bean
    for (Class<?> componentClass : componentClasses) {
        registerBean(componentClass);
    }
}

public void registerBean(Class<?> beanClass) {
    // 注册单个组件bean
    doRegisterBean(beanClass, null, null, null, null);
}

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
                                @Nullable Class<? extends Annotation>[] qualifiers, 
                                @Nullable Supplier<T> supplier,
                                @Nullable BeanDefinitionCustomizer[] customizers) {

    // 根据beanClass,构建AnnotatedGenericBeanDefinition(AnnotationMetadata + MethodMetadata)
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }

    abd.setInstanceSupplier(supplier);

    // 解析 @Scope
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());

    // 获取 beanName(指定了用指定的,否则用默认的)
    String beanName = (name != null ? name : 
                       this.beanNameGenerator.generateBeanName(abd, this.registry));

    // 处理 一些通用注解(@Lazy、@Primary、@DependsOn、@Role、@Description)
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

    // 处理 qualifiers
    if (qualifiers != null) {
        for (Class<? extends Annotation> qualifier : qualifiers) {
            // 如果配置了@Primary注解,设置该Bean为autowiring自动依赖注入装配时的首选
            if (Primary.class == qualifier) {
                abd.setPrimary(true);
            }
            // 如果配置了@Lazy注解,则设置该Bean为非延迟初始化
            else if (Lazy.class == qualifier) {
                abd.setLazyInit(true);
            }
            // 如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一个autowiring自动依赖注入装配限定符
            // 该Bean在进autowiring自动依赖注入装配时,根据名称装配限定符指定的Bean
            else {
                abd.addQualifier(new AutowireCandidateQualifier(qualifier));
            }
        }
    }

    // 应用 BeanDefinitionCustomizer 的 customize 方法
    if (customizers != null) {
        for (BeanDefinitionCustomizer customizer : customizers) {
            customizer.customize(abd);
        }
    }

    // 构建 BeanDefinitionHolder
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
 
    // 处理 @Scope 的 proxyMode 属性(如果需要代理,这里返回的是代理bd,但beanName不变)
    definitionHolder = AnnotationConfigUtils.
        applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

    // 注册 BeanDefinition
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

3、scanner 的获取

// org.springframework.web.context.support.AnnotationConfigWebApplicationContext

protected ClassPathBeanDefinitionScanner getClassPathBeanDefinitionScanner(DefaultListableBeanFactory beanFactory) {
    return new ClassPathBeanDefinitionScanner(beanFactory, true, getEnvironment());
}
// org.springframework.context.annotation.ClassPathBeanDefinitionScanner

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
                                      Environment environment) {
    // 参数的 registry 就是 beanFactory,useDefaultFilters 就是 true
    this(registry, useDefaultFilters, environment,
         (registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
                                      Environment environment, @Nullable ResourceLoader resourceLoader) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    this.registry = registry;

    if (useDefaultFilters) {
        // 注册默认的过滤器
        registerDefaultFilters();
    }

    setEnvironment(environment);
    setResourceLoader(resourceLoader);
}
// org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider

protected void registerDefaultFilters() {
    // Component.class
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();

    // javax.annotation.ManagedBean
    try {
        this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
        logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
        // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
    }

    // javax.inject.Named
    try {
        this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
        logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}

4、scanner.scan

// org.springframework.context.annotation.ClassPathBeanDefinitionScanner

public int scan(String... basePackages) {
    // 获取容器中已经注册的Bean个数
    int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

    // 扫描指定包的bean
    doScan(basePackages);

    // Register annotation config processors, if necessary.
    if (this.includeAnnotationConfig) {
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

    // 返回扫描注册的Bean个数
    return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");

    // 创建一个集合,存放扫描的BeanDefinition的封装
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();

    // 遍历要扫描的包
    for (String basePackage : basePackages) {
        // ------------------------------------------
        // 这里会真正执行资源扫描,并封装为BeanDefinition
        // ------------------------------------------
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        for (BeanDefinition candidate : candidates) {
            // 解析 @Scope
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            // 获取 beanName
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            // AbstractBeanDefinition 类型
            if (candidate instanceof AbstractBeanDefinition) {
                // 给 beanDefinition 设置 一些默认值 和 autowireCandidate
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            // AnnotatedBeanDefinition 类型
            if (candidate instanceof AnnotatedBeanDefinition) {
                // 处理一些通用注解(@Lazy、@Primary、@DependsOn、@Role、@Description)
                AnnotationConfigUtils.processCommonDefinitionAnnotations(
                    (AnnotatedBeanDefinition) candidate);
            }
            if (checkCandidate(beanName, candidate)) {
                // 构建 BeanDefinitionHolder
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                // 处理 @Scope 的 proxyMode 属性(如果需要代理,这里返回的是代理bd,但beanName不变)
                definitionHolder = AnnotationConfigUtils.
                    applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                // 注册bean
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }

    return beanDefinitions;
}

protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, 
                                      BeanDefinitionRegistry registry) {
    // 和reader一样,最终调用 BeanDefinitionReaderUtils 的 registerBeanDefinition 方法进行注册
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}

5、@Scope 的 proxyMode

无论是 reader.register 还是 scanner.scan,都能看到这样一段代码

// 处理 @Scope 的 proxyMode 属性
definitionHolder = AnnotationConfigUtils.
    applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

这块代码主要处理了 @Scope 注解的 proxyMode 属性。

1)@Scope

首先我们看一下 @Scope 的属性

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {
    @AliasFor("scopeName")
	String value() default "";

    @AliasFor("value")
	String scopeName() default "";

    // 代理模式,默认不创建代理
    ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}
public enum ScopedProxyMode {
    DEFAULT,		// 一般等同于NO,除非在组件扫描指令级别配置了不同的默认值
    NO,				// 不创建代理对象
    INTERFACES,		// 使用jdk动态代理来创建代理对象
    TARGET_CLASS	// 使用cglib动态代理来创建代理对象
}

2)@Scope 的解析

public class AnnotatedBeanDefinitionReader {
    private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
    
    private <T> void doRegisterBean(...) {
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
    }
}
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
    private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();

    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
    }
}

可以看到,无论是 reader 还是 scanner,最终都是通过 AnnotationScopeMetadataResolver 解析 @Scope 的

// org.springframework.context.annotation.AnnotationScopeMetadataResolver

private final ScopedProxyMode defaultProxyMode;

public AnnotationScopeMetadataResolver() {
    this.defaultProxyMode = ScopedProxyMode.NO;
}

@Override
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
    ScopeMetadata metadata = new ScopeMetadata();
    if (definition instanceof AnnotatedBeanDefinition) {
        AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
        AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
            annDef.getMetadata(), this.scopeAnnotationType);
        if (attributes != null) {
            metadata.setScopeName(attributes.getString("value"));
            ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
            // ScopedProxyMode.DEFAULT 使用 ScopedProxyMode.NO 的 proxyMode 值
            if (proxyMode == ScopedProxyMode.DEFAULT) {
                proxyMode = this.defaultProxyMode;
            }
            metadata.setScopedProxyMode(proxyMode);
        }
    }
    return metadata;
}

3)applyScopedProxyMode

然后,我们再看一下 AnnotationConfigUtils 的 applyScopedProxyMode 方法是怎么处理 @Scope 的 proxyMode 属性的

// org.springframework.context.annotation.AnnotationConfigUtils

static BeanDefinitionHolder applyScopedProxyMode(
    ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {

    // 获取 @Scope 的 proxyMode 属性
    ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();

    // proxyMode 的值为 NO 或 DEFAULT
    if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
        // 直接返回
        return definition;
    }

    // proxyMode 的值为 INTERFACES 或 TARGET_CLASS

    // 是否为cglib动态代理(INTERFACES 表示使用jdk动态代理;TARGET_CLASS 表示使用cglib动态代理)
    boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);

    // 创建Scope代理
    return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
// org.springframework.context.annotation.ScopedProxyCreator

public static BeanDefinitionHolder createScopedProxy(
    BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {
    
    return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
}
// org.springframework.aop.scope.ScopedProxyUtils

public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
                                                     BeanDefinitionRegistry registry, 
                                                     boolean proxyTargetClass) {
    String originalBeanName = definition.getBeanName();
    BeanDefinition targetDefinition = definition.getBeanDefinition();

    // targetBeanName = "scopedTarget." + originalBeanName
    String targetBeanName = getTargetBeanName(originalBeanName);

    // 创建代理的 BeanDefinition
    RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
    proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
    proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
    proxyDefinition.setSource(definition.getSource());
    proxyDefinition.setRole(targetDefinition.getRole());
    proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);

    // 是否为cglib动态代理
    if (proxyTargetClass) {
        // cglib动态代理
        targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
        // ScopedProxyFactoryBean 的 proxyTargetClass 默认为TRUE,因此这里不需要显式设置
    } else {
        // jdk动态代理
        proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
    }

    // Copy autowire settings from original bean definition.
    proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
    proxyDefinition.setPrimary(targetDefinition.isPrimary());
    if (targetDefinition instanceof AbstractBeanDefinition) {
        proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
    }

    // 原来的 BeanDefinition 不作为注入的候选者
    targetDefinition.setAutowireCandidate(false);
    targetDefinition.setPrimary(false);

    // 单独注册目标bean(beanName = "scopedTarget." + originalBeanName)
    registry.registerBeanDefinition(targetBeanName, targetDefinition);

    // 这里beanName还是用的原始的,但是beanDefinition已经替换成代理的了
    return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
}

4)ScopedProxyFactoryBean

applyScopedProxyMode 返回的 BeanDefinitionHolder 的 BeanDefinition 的 beanClass 被改成了 ScopedProxyFactoryBean

public class ScopedProxyFactoryBean extends ProxyConfig
    implements FactoryBean<Object>, BeanFactoryAware, AopInfrastructureBean {...}

ScopedProxyFactoryBean 实现了 FactoryBean,重写了以下方法

// org.springframework.aop.scope.ScopedProxyFactoryBean

@Nullable
private Object proxy;

@Override
public Object getObject() {
    if (this.proxy == null) {
        throw new FactoryBeanNotInitializedException();
    }
    // 返回的是代理对象
    return this.proxy;
}

@Override
public Class<?> getObjectType() {
    if (this.proxy != null) {
        return this.proxy.getClass();
    }
    return this.scopedTargetSource.getTargetClass();
}

@Override
public boolean isSingleton() {
    return true;
}

ScopedProxyFactoryBean 还实现了 BeanFactoryAware,重写了 setBeanFactory 方法(proxy 就是在这里生成的)

// org.springframework.aop.scope.ScopedProxyFactoryBean

private final SimpleBeanTargetSource scopedTargetSource = new SimpleBeanTargetSource();

@Override
public void setBeanFactory(BeanFactory beanFactory) {
    if (!(beanFactory instanceof ConfigurableBeanFactory)) {
        throw new IllegalStateException("Not running in a ConfigurableBeanFactory: " + beanFactory);
    }
    ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;

    this.scopedTargetSource.setBeanFactory(beanFactory);

    ProxyFactory pf = new ProxyFactory();
    pf.copyFrom(this);
    pf.setTargetSource(this.scopedTargetSource);

    // ...

    // 创建代理对象
    this.proxy = pf.getProxy(cbf.getBeanClassLoader());
}

Cglib 代理 会进入到 CglibAopProxy 的内部类 DynamicAdvisedInterceptor 的 intercept 方法

// org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor

@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    // ...

    // getTargetSource() 获取到的就是上面的 scopedTargetSource 对象(new SimpleBeanTargetSource)
    TargetSource targetSource = this.advised.getTargetSource();
    try {
        // ...

        // 这里调用的是 SimpleBeanTargetSource 的 getTarget()
        target = targetSource.getTarget();

        // ...
    } 
    // ...
}
public class SimpleBeanTargetSource extends AbstractBeanFactoryBasedTargetSource {
    @Override
    public Object getTarget() throws Exception {
        // 触发 getBean(),如果是 prototype,每次都会返回一个新的 bean
        return getBeanFactory().getBean(getTargetBeanName());
    }
}

5)小结

  • @Scope 的 proxyMode 为 DEFAULT 和 NO —> 只会有一个 BeanDefinition,就是原始的 Bean
  • @Scope 的 proxyMode 为 INTERFACES 或 TARGET_CLASS —> 会有两个 BeanDefinition
    • 原始的 BeanDefinition:beanName = “scopedTarget.” + originalBeanName(不会作为注入的候选者)
    • 代理的 BeanDefinition:beanName = originalBeanName(beanClass = ScopedProxyFactoryBean.class)

BeanDefinition 中的 beanClass 被偷梁换柱成了 ScopedProxyFactoryBean,获取bean通过 getObject 返回 proxy

三、BeanDefinition 的注册

无论是 reader 还是 scanner,最终都会调用 BeanDefinitionReaderUtils 的 registerBeanDefinition 方法进行注册

// org.springframework.beans.factory.support.BeanDefinitionReaderUtils

public static void registerBeanDefinition(
    BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
    throws BeanDefinitionStoreException {

    // 注册 BeanDefinition
    // 将 <beanName, beanDefinition> 存入 DefaultListableBeanFactory 的 beanDefinitionMap 中
    String beanName = definitionHolder.getBeanName();
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    // 注册 aliases 别名
    // 将 <alias, beanName> 存入 aliasesMap 中,获取bean时,先根据alias找到beanName,然后再获取bean
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

1、registerBeanDefinition

BeanDefinitionReaderUtils 通过 BeanDefinitionRegistry 的 registerBeanDefinition 方法 注册 BeanDefinition

// BeanDefinitionRegistry 继承了 AliasRegistry
public interface BeanDefinitionRegistry extends AliasRegistry {
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException;
}

而 DefaultListableBeanFactory 实现了 BeanDefinitionRegistry 接口,重写了 registerBeanDefinition 方法

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
    // DefaultListableBeanFactory 实现了 BeanDefinitionRegistry
    implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {...}

因此,reader.register 和 scanner.scan 最终都会走到 DefaultListableBeanFactory 重写的 registerBeanDefinition 方法

// org.springframework.beans.factory.support.DefaultListableBeanFactory
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    throws BeanDefinitionStoreException {

    // 一些校验...

    // 判断 BeanDefinition 是否已存在
    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);

    // 当前 BeanDefinition 已存在
    if (existingDefinition != null) {
        // 是否允许bean覆盖
        if (!isAllowBeanDefinitionOverriding()) {
            throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
        } 
        // ...
        // bean覆盖
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }

    // 当前 BeanDefinition 不存在
    else {
        // 检查这个工厂的bean创建阶段是否已经开始,即是否有任何bean在此期间被标记为已创建。
        
        // 已经开始创建Bean了
        if (hasBeanCreationStarted()) {
            // 这种情况需要加锁
            synchronized (this.beanDefinitionMap) {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                removeManualSingletonName(beanName);
            }
        }

        // 还没有开始创建Bean
        else {
            // 将 BeanDefinition 存入 DefaultListableBeanFactory 的 beanDefinitionMap 中
            // beanDefinitionMap 这个 map 保存了所有的 BeanDefinition
            this.beanDefinitionMap.put(beanName, beanDefinition);
            // 这是个 ArrayList,所以会按照 bean 配置的顺序保存每一个注册的 Bean 的名字
            this.beanDefinitionNames.add(beanName);
            // 从手动注册的集合里删除,走到这里的 Bean 不是手动注册的
            // 手动指的是调用 registerSingleton(String beanName, Object singletonObject) 注册
            removeManualSingletonName(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }

    if (existingDefinition != null || containsSingleton(beanName)) {
        // 重置所有已经注册过的 BeanDefinition 的缓存
        resetBeanDefinition(beanName);
    }

    else if (isConfigurationFrozen()) {
        clearByTypeCache();
    }
}

2、registerAlias

  • register.registerAlias 最终调用的是 SimpleAliasRegistry 中的 registerAlias 方法
  • DefaultListableBeanFactory 也是 SimpleAliasRegistry 的子类

在这里插入图片描述

public class SimpleAliasRegistry implements AliasRegistry {
    
    protected final Log logger = LogFactory.getLog(this.getClass());

    // 保存别名信息的map:<alias, beanName>
    // 获取bean的时候,先根据 alias 获取 beanName,然后再查找bean
    private final Map<String, String> aliasMap = new ConcurrentHashMap(16);

    public SimpleAliasRegistry() {}

    public void registerAlias(String name, String alias) {
        Assert.hasText(name, "'name' must not be empty");
        Assert.hasText(alias, "'alias' must not be empty");
        
        synchronized(this.aliasMap) {
            if (alias.equals(name)) {
                // alias 和 beanName 一致
                this.aliasMap.remove(alias);
                
                // logger...
            } else {
                String registeredName = (String) this.aliasMap.get(alias);
                if (registeredName != null) {
                    // alias已存在
                    if (registeredName.equals(name)) {
                        return;
                    }

                    // alias对应的beanName不一致
                    
                    // 不允许
                    if (!this.allowAliasOverriding()) {
                        throw new IllegalStateException(...);
                    }

                    // logger...
                }

                this.checkForAliasCircle(name, alias);
                
                // 保存 <alias, beanName>
                this.aliasMap.put(alias, name);
                
                // logger...
            }

        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1561691.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅谈高阶智能驾驶-NOA领航辅助的技术与发展

浅谈高阶智能驾驶-NOA领航辅助的技术与发展 附赠自动驾驶学习资料和量产经验&#xff1a;链接 2019年在国内首次试驾特斯拉NOA领航辅助驾驶的时候&#xff0c;当时兴奋的觉得未来已来;2020年在试驾蔚来NOP领航辅助驾驶的时候&#xff0c;顿时不敢小看国内新势力了;现在如果哪家…

第十八章 算法

一、介绍 1.1 什么是算法 算法&#xff08;Algorithm&#xff09;是指解题方案的准确而完整的描述&#xff0c;是一系列解决问题的清晰指令&#xff0c;算法代表着用系统的方法描述解决问题的策略机制。也就是说&#xff0c;能够对一定规范的输入&#xff0c;在有限时间内获…

kubernetes之实战进阶篇

目录 一、搭建kubenetes集群 1.1、搭建方案选择 1.2、软硬件准备 1.2.1、硬件要求: 1.2.2、软件要求 1.3、安装步骤 1.3.1、初始化操作(三个节点都要执行一遍) 1.3.2、部署kubernetes master节点(控制面板) 1.3.3、node节点加入k8s集群 1.3.4、部署CNI网络插件 1.3.…

【经典算法】LeetCode14:最长公共前缀(Java/C/Python3实现含注释说明,Easy)

最长公共前缀 题目思路及实现方式一&#xff1a;横向扫描思路代码实现Java版本C语言版本Python3版本 复杂度分析 方式二&#xff1a;纵向扫描思路代码实现Java版本C语言版本Python3版本 复杂度分析 方式三&#xff1a;分治思路代码实现Java版本C语言版本Python3版本 复杂度分析…

VBA技术资料MF136:复制整个数据范围到PowerPoint

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

Php_Code_challenge13

题目&#xff1a; 答案&#xff1a; 解析&#xff1a; 开启一个会话&#xff0c;在SESSION变量"nums"为空时则对"nums","time","whoami"进行赋值&#xff0c;并在120秒后关闭会话&#xff0c;创建一个变量"$value"…

【算法集训】基础算法:前缀和 | 概念篇

前缀和就是对于顺序表&#xff08;数组、列表&#xff09;来说&#xff0c;计算前面某一段元素的和。 1、部分和 给定一个数组&#xff0c;求某一段子数组的和。 2、朴素做法 int partialSum(int *a, int l, int r) {int i;int s 0;for(i l; i < r; i) {s a[i];}retu…

蓝桥杯单片机速成4-温度传感器DS18B20

目录 一、电路图 二、底层驱动代码 三、温度读取实现 四、实际使用 一、电路图 二、底层驱动代码 时序是单总线 我们需要修改的地方是单总线内部延时函数&#xff0c;改成 void Delay_OneWire(unsigned int t) { t*12; while(t--); } #ifndef __ONEWIRE_H #defi…

ZKFair 步入Dargon Slayer 新阶段,未来还有哪些财富效应?

在当前区块链技术的发展中&#xff0c;Layer 2&#xff08;L2&#xff09;解决方案已成为提高区块链扩容性、降低交易成本和提升交易速度的关键技术&#xff0c;但它仍面临一些关键问题和挑战&#xff0c;例如用户体验的改进、跨链互操作性、安全性以及去中心化程度。在这些背景…

HQL,SQL刷题,尚硅谷(初级)

目录 相关表数据&#xff1a; 题目及思路解析&#xff1a; 多表连接 1、课程编号为"01"且课程分数小于60&#xff0c;按分数降序排列的学生信息 2、查询所有课程成绩在70分以上 的学生的姓名、课程名称和分数&#xff0c;按分数升序排列 3、查询该学生不同课程的成绩…

Linux多进程通信(2)——POSIX信号量使用例程

1.POSIX信号量 1&#xff09;POSIX信号量和System V信号量区别 常用的是POSIX信号量&#xff0c;使用起来更加方便&#xff0c;而POSIX信号量分为有名信号量和无名信号量 POSIX信号量是多线程多进程安全的&#xff0c;而System V标准的信号量并不是&#xff0c;Posix通过sem_…

java----继承

1、继承的定义 继承就是子类继承父类的特征和行为&#xff0c;使得子类对象具有父类的属性和方法&#xff08;不劳而获&#xff09; 使用 extends关键字 2、方法重写&#xff08;方法覆盖&#xff09; 子类可以重写父类中的方法&#xff0c;要求方法签名必须一样 3、方法重载…

2、jvm基础知识(二)

类的生命周期 加载 1、加载(Loading)阶段第一步是类加载器根据类的全限定名通过不同的渠道以二进制流的方式获取字节码信息。 程序员可以使用Java代码拓展的不同的渠道。 2、类加载器在加载完类之后&#xff0c;Java虚拟机会将字节码中的信息保存到内存的方法区中。在方法区生…

【已解决】Port 8080 was already in use

问题描述 运行项目时显示错误页&#xff0c;无法成功进入目标页 *************************** APPLICATION FAILED TO START ***************************Description:Web server failed to start. Port 8080 was already in use.Action:Identify and stop the process thats…

MySQL常见故障案例与优化介绍

前言 MySQL故障排查的意义在于及时识别并解决数据库系统中的问题&#xff0c;确保数据的完整性和可靠性&#xff1b;而性能优化则旨在提高数据库系统的效率和响应速度&#xff0c;从而提升用户体验和系统整体性能。这两方面的工作都对于保证数据库系统稳定运行、提升业务效率和…

html基础:颜色的 5 种表示方法(最全!)

你好&#xff0c;我是云桃桃。一个希望帮助更多朋友快速入门 WEB 前端的程序媛&#xff0c;大专生&#xff0c;2年时间从1800到月入过万&#xff0c;工作5年买房。 分享成长心得。 HTML 颜色在网页设计中扮演着重要角色&#xff0c;给网页增加颜色可以增强用户体验&#xff0c;…

臻奶惠无人售货机:新零售时代的便捷消费革命

臻奶惠无人售货机&#xff1a;新零售时代的便捷消费革命 在新零售的浪潮中&#xff0c;智能无人售货机作为一个创新的消费模式&#xff0c;已经成为距离消费者最近的便捷购物点之一。这种模式不仅能够满足居民对消费升级的需求&#xff0c;还能通过建立多样化和多层次的消费体…

Spring使用(一)注解

Spring使用 资源 Spring 框架内部使用 Resource 接口作为所有资源的抽象和访问接口&#xff0c;在上一篇文章的示例代码中的配置文件是通过ClassPathResource 进行封装的&#xff0c;ClassPathResource 是 Resource 的一个特定类型的实现&#xff0c;代表的是位于 classpath …

Python创建三维空间立体方阵,根据赋予数值绘图赋色

代码如下&#xff1a; import matplotlib.pyplot as plt from mpl_toolkits.mplot3d.art3d import Poly3DCollection from matplotlib.colors import LinearSegmentedColormap, Normalize import numpy as npdef make_cube(matrix: np.ndarray)->None:fig plt.figure(figs…

vue项目视频播放ckplayer使用

ckplayer 官方网址&#xff0c;点击访问 1&#xff0c;打开网页后能看到这里&#xff0c;我现在使用的是最新 X3版手册 2&#xff0c;这个ckplayer不是npm 插件&#xff0c;要下载安装包解压到项目里面使用 安装包网址 通过gitee下载 3&#xff0c;解析安装包到项目中 publ…