Ioc容器——AnnotationConfigApplicationContext

Ioc容器——AnnotationConfigApplicationContext

1. Spring 官方文档

You should use an ApplicationContext unless you have a good reason for not doing so, with GenericApplicationContext and its subclass AnnotationConfigApplicationContext as the common implementations for custom bootstrapping. These are the primary entry points to Spring’s core container for all common purposes: loading of configuration files, triggering a classpath scan, programmatically registering bean definitions and annotated classes, and (as of 5.0) registering functional bean definitions.

大致意思是说:

能使用ApplicationContext就不是用BeanFactory。用GenericApplicationContext及其子类AnnotationConfigAppliactionContext 作为自定义引导的常用实现。这几个是Spring核心容器的主要入口点,用于加载配置文件、触发类路径扫描、以编程的方式注册Bean定义和带注释的类,以及从5.0开始的注册功能性Bean定义。

2. AnnotationConfigApplicationContext源码

在这里插入图片描述

AnnotationConfigApplicationContext 是Spring3.0以后引入的类,用于处理Spring注解,使用AnnotationConfigApplicationContext可以实现基于Java的配置类加载Spring的应用上下文,避免使用application.xml 进行配置。相比XML配置,更加便捷。

AnnotationConfigApplicationContext继承于GenericApplicationContext,而GenericApplicationContext继承于BeanDefinitionRegistry。Spring容器是通过BeanDefinition对象来表示Bean的,BeanDefinition描述了Bean的相关信息。

BeanDefinitionRegistry接口提供了向容器中注册、删除、获取BeanDefinition对象的方法。简单来说就是BeanDefinitionRegistry可以管理BeanDefinition,也就是说AnnotationConfigApplicationContext是管理Bean的重要类。

package org.springframework.context.annotation;

import java.util.function.Supplier;

import org.springframework.beans.factory.config.BeanDefinitionCustomizer;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

    /**
     * Bean读取器
     */
	private final AnnotatedBeanDefinitionReader reader;

    /**
     * 类扫描器
     */
	private final ClassPathBeanDefinitionScanner scanner;

	public AnnotationConfigApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

	public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
		super(beanFactory);
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

    /**
     * 创建一个AnnotationConfigApplicationContext,并再给定包路径下的BeanDefinitions进行扫描。
     */
	public AnnotationConfigApplicationContext(String... basePackages) {
		this();
        //扫描指定包路径下的类
		scan(basePackages);
        //刷新上下文
		refresh();
	}


	@Override
	public void setEnvironment(ConfigurableEnvironment environment) {
		super.setEnvironment(environment);
		this.reader.setEnvironment(environment);
		this.scanner.setEnvironment(environment);
	}

	public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
		this.reader.setBeanNameGenerator(beanNameGenerator);
		this.scanner.setBeanNameGenerator(beanNameGenerator);
		getBeanFactory().registerSingleton(
				AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
	}

	public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
		this.reader.setScopeMetadataResolver(scopeMetadataResolver);
		this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
	}

    /**
     * 按指定Bean配置类读取Bean
     */
	public void register(Class<?>... annotatedClasses) {
		Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
		this.reader.register(annotatedClasses);
	}

    /**
     * 扫描指定的包
     */
	public void scan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		this.scanner.scan(basePackages);
	}

	/**
	 * 注册Bean
	 */
	public <T> void registerBean(Class<T> annotatedClass, Object... constructorArguments) {
		registerBean(null, annotatedClass, constructorArguments);
	}

	public <T> void registerBean(@Nullable String beanName, Class<T> annotatedClass, Object... constructorArguments) {
		this.reader.doRegisterBean(annotatedClass, null, beanName, null,
				bd -> {
					for (Object arg : constructorArguments) {
						bd.getConstructorArgumentValues().addGenericArgumentValue(arg);
					}
				});
	}

	@Override
	public <T> void registerBean(@Nullable String beanName, Class<T> beanClass, @Nullable Supplier<T> supplier,
			BeanDefinitionCustomizer... customizers) {

		this.reader.doRegisterBean(beanClass, supplier, beanName, null, customizers);
	}

}

  • refresh

    refresh方法在AbstractApplicationContext容器中实现,refresh()方法的作用加载或者刷新当前的配置信息,如果已经存在spring容器,则先销毁之前的容器,重新创建spring容器,载入bean定义,完成容器初始化工作,所以可以看出AnnotationConfigApplicationContext容器是通过调用其父类AbstractApplicationContextrefresh()函数启动整个IoC容器完成对Bean定义的载入。

3. BeanDefinitionRegistry

在这里插入图片描述

将定义 bean 的资源文件解析成 BeanDefinition 后需要将其注入容器中,这个过程由 BeanDefinitionRegistry来完成。

BeanDefinitionRegistry继承了 AliasRegistry接口,其核心子类有三个:SimpleBeanDefinitionRegistryDefaultListableBeanFactoryGenericApplicationContext

BeanDefinition 的注册接口,如 RootBeanDefinitionChildBeanDefinition。它通常由 BeanFactories 实现,在 Spring 中已知的实现者为:DefaultListableBeanFactoryGenericApplicationContextBeanDefinitionRegistry 是 Spring 的 Bean 工厂包中唯一封装 BeanDefinition 注册的接口。

package org.springframework.beans.factory.support;

import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.core.AliasRegistry;

/**
 * BeanDefinitionRegistry 接口定义了关于 BeanDefinition 注册、注销、查询等一系列的操作。
 */
public interface BeanDefinitionRegistry extends AliasRegistry {
    //向注册表中注册一个新的BeanDefinition
    void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
	//移除注册表中已注册的BeanDefinition
    void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
	//从注册表中获取一个BeanDefinition的实例
    BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
	//判断是否包含BeanDefinition实例
    boolean containsBeanDefinition(String var1);
	//获取注册表中所有BeanDefinition实例的beanName标识
    String[] getBeanDefinitionNames();
	//返回注册表中BeanDefinition实例的数量
    int getBeanDefinitionCount();
	//beanName是否已经被占用
    boolean isBeanNameInUse(String var1);
}

1. SimpleBeanDefinitionRegistry

SimpleBeanDefinitionRegistryBeanDefinitionRegistry的一个简单实现,它还继承了SimpleAliasRegistry,仅仅提供注册表的功能。


package org.springframework.beans.factory.support;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.core.SimpleAliasRegistry;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {
    //使用ConcurrentHashMap来注册BeanDefinition
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(64);

    public SimpleBeanDefinitionRegistry() {
    }

    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
        Assert.hasText(beanName, "'beanName' must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }

    public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
        if (this.beanDefinitionMap.remove(beanName) == null) {
            throw new NoSuchBeanDefinitionException(beanName);
        }
    }

    public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
        BeanDefinition bd = (BeanDefinition)this.beanDefinitionMap.get(beanName);
        if (bd == null) {
            throw new NoSuchBeanDefinitionException(beanName);
        } else {
            return bd;
        }
    }

    public boolean containsBeanDefinition(String beanName) {
        return this.beanDefinitionMap.containsKey(beanName);
    }

    public String[] getBeanDefinitionNames() {
        return StringUtils.toStringArray(this.beanDefinitionMap.keySet());
    }

    public int getBeanDefinitionCount() {
        return this.beanDefinitionMap.size();
    }

    public boolean isBeanNameInUse(String beanName) {
        return this.isAlias(beanName) || this.containsBeanDefinition(beanName);
    }
}

SimpleBeanDefinitionRegistry 的功能实现都是依赖于beanDefinitionMap ,简单粗暴。

2. DefaultListableBeanFactory

DefaultListableBeanFactory 继承于ConfigurableListableBeanFactory, BeanDefinitionRegistry接口,一个基于BeanDefinition 元数据的完整的Bean工厂。同样使用ConcurrentHashMap 来存储注册的BeanDefinition


	/**
	 * 注册表,key-beanName,value-BeanDefinition实例
	 */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
	
	/**
	 * 所有beanName的集合
	 */
    private volatile List<String> beanDefinitionNames = new ArrayList(256);

  • registerBeanDefinition()

注册BeanDefinition 的方法

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");
        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                ((AbstractBeanDefinition)beanDefinition).validate();
            } catch (BeanDefinitionValidationException var8) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);
            }
        }

        BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
        //beanDefinitionMap中不存在实例
    	if (existingDefinition != null) {
            //....省略
            this.beanDefinitionMap.put(beanName, beanDefinition);
        } 
    	//已经存在实例
    	else {
            //检查factory's bean 是否开始创建
            if (this.hasBeanCreationStarted()) {
                Map var4 = this.beanDefinitionMap;
                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;
                    this.removeManualSingletonName(beanName);
                }
            } else {
                //注册 BeanDefinition
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                this.removeManualSingletonName(beanName);
            }

            this.frozenBeanDefinitionNames = null;
        }

        if (existingDefinition != null || this.containsSingleton(beanName)) {
            this.resetBeanDefinition(beanName);
        }

    }

4. AnnotatedBeanDefinitionReader

AnnotationConfigApplicationContext 注册BeanDefinition 是通过AnnotatedBeanDefinitionReader 类来实现的,调用的都是AnnotatedBeanDefinitionReaderdoRegisterBean()

//完成bean配置类本身的解析和注册
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

    	//先把实体类型转化成BeanDefinition类型
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
		//abd.getMetadata 获取BeanDefinition的元数据信息:注解信息、是否内部类、类Class基本信息
    	//conditionEvaluator.shouldskip 判断此类是否为配置类
    	//@Conditional装配条件判断是否需要跳过注册
    	if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}
		//
		abd.setInstanceSupplier(instanceSupplier);
		//解析bean作用域(单例或者原型),如果有@Scope注解,则解析@Scope,没有则默认为singleton 
    	ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
		//得到beanName,一般为首字母小写的类名
   		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
		//设定注解的默认值
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		//解析qualifiers 若有此注解,则primary设置为true
    	if (qualifiers != null) {
             //
			for (Class<? extends Annotation> qualifier : qualifiers) {
				//如果配置了@Primary注解,则设置当前的bean为制动装配autowired首选
                if (Primary.class == qualifier) {
					abd.setPrimary(true);
				}
                //懒加载/延迟加载
				else if (Lazy.class == qualifier) {
					abd.setLazyInit(true);
				}
                //其他注解添加到abd结构中
				else {
					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
				}
			}
		}
    	//自定义定制信息(一般都不需要)
		for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
			customizer.customize(abd);
		}
		//根据beanName和bean定义信息封装一个beanhold
    	//heanhold其实就是一个 beanname和BeanDefinition的映射
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		//创建代理对象
    	definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    	// 实际上DefaultListableBeanFactory内部维护一个Map<String, BeanDefinition>
    	//类型变量beanDefinitionMap,
        //用于保存注bean定义信息(beanname 和 beandefine映射)
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

5. ClassPathBeanDefinitionScanner

ClassPathBeanDefinitionScanner 是一个扫描指定类路径中注解Bean定义的扫描器,在初始化的时候,会初始化一些需要被扫描的注解,初始化用于加载包下的资源loader

AnnotatedBeanDefinitionReaderClassPathBeanDefinitionScanner 是Spring上下文初始化的起点,很多预加载的类会在spring接下来初始化发挥重要作用。

	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		// 装载扫描到的Bean	
    	Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		
        for (String basePackage : basePackages) {
			//重点就是将扫描的bean放进来
             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);
                 //添加bean的定义信息
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
                
				//如果是实现注解的beandefinition,然后把注解解析成属性
				if (candidate instanceof AnnotatedBeanDefinition) {
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
                  //检查bean
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
                    //把Bean注册到factory
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}
  • BeanDefinitionHolder
	//BeanDefinitionHolder是BeanDefinition的持有者	
	//BeanDefinitionHolder中三个属性	

	private final BeanDefinition beanDefinition;

	private final String beanName;

	@Nullable
	private final String[] aliases;
  • findCandidateComponents

findCandidateComponentsClassPathScanningCandidateComponentProvider提供的

	//找到包下的组件
	public Set<BeanDefinition> findCandidateComponents(String basePackage) {
		// CandidateComponentsIndex是Spring5提供的优化扫描的功能
		// 显然这里编译器我们没有写META-INF/spring.components索引文件,
        // 所以此处不会执行Spring5 的扫描方式
        if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
            //spring5优化方案
			return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
		}
		else {
            //spring5之前的方式
			return scanCandidateComponents(basePackage);
		}
	}
  • scanCandidateComponents (important)

scanCandidateComponentsClassPathScanningCandidateComponentProvider提供的

	//扫描此包,然后返回此包下的所有的Bean的set集合
	private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
		
        Set<BeanDefinition> candidates = new LinkedHashSet<>();
		
        try {
            //根据指定包名,生成包搜索路径
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
			//加载资源路径下的所有class,转化为resource[]
            Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
			//日志方面 后面将删除掉所有日志信息 
            boolean traceEnabled = logger.isTraceEnabled();
            boolean debugEnabled = logger.isDebugEnabled();
			
            for (Resource resource : resources) {
				//resource必须是可读
				if (resource.isReadable()) {
					try {
                        //读取类的注解信息和类信息,将信息储存到MetadataReader
						MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                        //通过TypeFilters过滤排除组件
						if (isCandidateComponent(metadataReader)) {
						//将符合条件的类转化成BeanDefinition	
                            ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
							sbd.setResource(resource);
							sbd.setSource(resource);
                            //再次判断是否为实体类,或者抽象类中有@Lookup
							if (isCandidateComponent(sbd)) {
								candidates.add(sbd);
							}
						}
					}
				}
			}
		}
		return candidates;
	}

  • postProcessBeanDefinition

	protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
		//执行默认的信息
    	beanDefinition.applyDefaults(this.beanDefinitionDefaults);
		//自动DI,匹配路径
    	if (this.autowireCandidatePatterns != null) {
			beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName));
		}
	}
	//AbstractBeanDefinition中实现的方法
	public void applyDefaults(BeanDefinitionDefaults defaults) {
		setLazyInit(defaults.isLazyInit());
		setAutowireMode(defaults.getAutowireMode());
		setDependencyCheck(defaults.getDependencyCheck());
		setInitMethodName(defaults.getInitMethodName());
		setEnforceInitMethod(false);
		setDestroyMethodName(defaults.getDestroyMethodName());
		setEnforceDestroyMethod(false);
	}

6. 感想

AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner两个起点来,个人感觉从ClassPathBeanDefinitionScanner出发更好理解Ioc容器。Spring的架构庞大,但是基本上每个类的设计都很巧妙,符合单一职责原则。总而言之,复杂但不冗杂。

7. 参考

https://www.cnblogs.com/ashleyboy/p/9662119.html

https://cloud.tencent.com/developer/article/1497799

http://cmsblogs.com/?p=4026

持续

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值