Spring源码导读之AnnotationConfigApplicationContext

Spring源码导读

目录

用法:scan,register

用法一:ClassPathBeanDefinitionScanner

用法二:AnnotatedBeanDefinitionReader


 

用法

scan: 扫描包下的类进行注册

register : 指定单个文件进行注册

public class AnnotationApplicaton {

    public static void main(String[] args) {
        /**
         * AnnotationConfigApplicationContext的两个成员变量
         * ClassPathBeanDefinitionScanner扫描指定包下面的class文件 如果满足条件
         * 1、被@component注解
         * 2、top level class 并且可以被实例化的类
         * AnnotatedBeanDefinitionReader : 注册指定的class
         */
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.scan("com.jack.ascp.purchase.app.test.spring.anno");
        applicationContext.register(Person.class);
        applicationContext.refresh();

        Person person = (Person)applicationContext.getBean("person");

        System.out.println(person.toString());
    }
}

可以在构造器中refresh, 也可以构造时不refresh而是交给用户手动refresh()。

四个构造函数

/**
 * 无参构造,需要手动scan或register,并且refresh
 */
public AnnotationConfigApplicationContext() {
	this.reader = new AnnotatedBeanDefinitionReader(this);
	this.scanner = new ClassPathBeanDefinitionScanner(this);
}

/**
 * 给定beanFactory构造,需要手动scan或register,并且refresh
 */
public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
	super(beanFactory);
	this.reader = new AnnotatedBeanDefinitionReader(this);
	this.scanner = new ClassPathBeanDefinitionScanner(this);
}

/**
 * 穿入多个class, 自动refresh()
 */
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
	this();
	register(annotatedClasses);
	refresh();
}

/**
 * 穿入多个包路径, 自动refresh()
 */
public AnnotationConfigApplicationContext(String... basePackages) {
	this();
	scan(basePackages);
	refresh();
}

 

用法一:ClassPathBeanDefinitionScanner

scan用法是通过ClassPathBeanDefinitionScanner完成的

public void scan(String... basePackages) {
	Assert.notEmpty(basePackages, "At least one base package must be specified");
	this.scanner.scan(basePackages);
}

ClassPathBeanDefinitionScanner#scan

这里会扫描满足的目标类,并且还会会注册注解模式下所需要的BeanPostProcessor(如果已经注册了,则不注册了),类似在xml模式下,我们配置了<context:annotation-config/> 在案例《AutowiredAnnotationBeanPostProcessor》也有过提到这个AnnotationConfigUtils.registerAnnotationConfigProcessors(

public int scan(String... basePackages) {
	// beanCountAtScanStart = 扫描之前bean的数量
	int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

	doScan(basePackages);

	// 注意, 这里会注册注解模式下所需要的BeanPostProcessor, 就像在xml模式下,我们配置了<context:annotation-config/> 也会调用这行代码
	if (this.includeAnnotationConfig) {
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}

	return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}

doScan(String... basePackages) 

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
	Assert.notEmpty(basePackages, "At least one base package must be specified");
	// Set<BeanDefinitionHolder> 用于存储扫描后的结果
	Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
	for (String basePackage : basePackages) {
		// 开始扫描
		Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
		for (BeanDefinition candidate : candidates) {
			// 设置它的scope信息,比如proxyMode 
			ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
			candidate.setScope(scopeMetadata.getScopeName());
			String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
			// 设置一些属性的默认值比如isLazyinit,autowireMode等等。
			// 这些默认值在xml模式下都是在schema文件中配置的默认值。但是基于注解模式的情况,我们需要手动设置这些默认值
			if (candidate instanceof AbstractBeanDefinition) {
				postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
			}
			// 再从类的注解上对这些属性进行再次修饰,比如配置了Lazy注解, 则将其isLazyinit的默认值覆盖。
			if (candidate instanceof AnnotatedBeanDefinition) {
				AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
			}
			// 检测: 检测这个beanDefinition是否已经注册过了
			if (checkCandidate(beanName, candidate)) {
				// 封装成BeanDefinitionHolder
				BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
				// 如果在注解上配置了属性 proxyMode 配置了, 会对对象进行代理, 类似在xml模式下的: <aop:scoped-proxy proxy-target-class="true"/>
				definitionHolder =
						AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
				// 将本次扫描到的BeanDefinitionHolder加入到Set进行返回, 用于告诉用户: scanner帮你扫描和注册了这些beanDefinition
				beanDefinitions.add(definitionHolder);
				// 注册到BeanDefinitionRegistry中
				registerBeanDefinition(definitionHolder, this.registry);
			}
		}
	}
	return beanDefinitions;
}

调用其父类ClassPathScanningCandidateComponentProvider#findCandidateComponents

ClassPathBeanDefinitionScanner 继承了 ClassPathScanningCandidateComponentProvider

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
	if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
		return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
	}
	else {
		return scanCandidateComponents(basePackage);
	}
}

scanCandidateComponents:

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
	Set<BeanDefinition> candidates = new LinkedHashSet<>();
	try {
		// 将aa.bb.cc 转为 classpath*:aa/bb/cc/**/*.class
		String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
				resolveBasePackage(basePackage) + '/' + this.resourcePattern;
		// 使用PathMatchingResourcePatternResolver找到路径下所有的class文件
		Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
		boolean traceEnabled = logger.isTraceEnabled();
		boolean debugEnabled = logger.isDebugEnabled();
		// 遍历文件资源
		for (Resource resource : resources) {
			if (traceEnabled) {
				logger.trace("Scanning " + resource);
			}
			if (resource.isReadable()) {
				try {
					// 获取MetadataReader : SimpleMetadataReader, SimpleMetadataReader其实依赖ClassReader 和 AnnotationMetadataReadingVisitor
					MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
					// 判断 resource 是否满足过滤要求, 用户可以自定义配置过滤, 比如要求被component注解
					if (isCandidateComponent(metadataReader)) {
						// 生成一个ScannedGenericBeanDefinition ,它继承了GenericBeanDefinition,它GenericBeanDefinition多了一个字段就是AnnotationMetadata metadata
						ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
						sbd.setResource(resource);
						sbd.setSource(resource);
						// 要求是一个(独立的&&具体的) || (抽象的类&&被Lookup注解的类)
						if (isCandidateComponent(sbd)) {
							if (debugEnabled) {
								logger.debug("Identified candidate component class: " + resource);
							}
							// 满足则加入列表当中,最后将其返回
							candidates.add(sbd);
						}
						else {
							if (debugEnabled) {
								logger.debug("Ignored because not a concrete top-level class: " + resource);
							}
						}
					}
					else {
						if (traceEnabled) {
							logger.trace("Ignored because not matching any filter: " + resource);
						}
					}
				}
				catch (Throwable ex) {
					throw new BeanDefinitionStoreException(
							"Failed to read candidate component class: " + resource, ex);
				}
			}
			else {
				if (traceEnabled) {
					logger.trace("Ignored because not readable: " + resource);
				}
			}
		}
	}
	catch (IOException ex) {
		throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
	}
	return candidates;
}

注意:生成ScannedGenericBeanDefinition ,它继承了GenericBeanDefinition,它GenericBeanDefinition多了一个字段就是AnnotationMetadata metadata:

注意:里面两个条件的判断:

使用includeFilters过滤器进行过滤

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
	for (TypeFilter tf : this.excludeFilters) {
		if (tf.match(metadataReader, getMetadataReaderFactory())) {
			return false;
		}
	}
	for (TypeFilter tf : this.includeFilters) {
		if (tf.match(metadataReader, getMetadataReaderFactory())) {
			return isConditionMatch(metadataReader);
		}
	}
	return false;
}

//  要求是一个(独立的&&具体的) || (抽象的类&&被Lookup注解的类)

protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
	AnnotationMetadata metadata = beanDefinition.getMetadata();
	return (metadata.isIndependent() && (metadata.isConcrete() ||
			(metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
}

我们可以继承ClassPathBeanDefinitionScanner重写registerDefaultFilters方法加入自己的includeFilter, 还可以重写isCandidateComponent实现自己对目标类的要求。

例如我在《模拟实现mabatis scanmapper》案例中: 我要求扫描的类被Repository注解,要求是一个interface,可以这么实现:

@Override
protected void registerDefaultFilters() {
	this.addIncludeFilter(new AnnotationTypeFilter(Repository.class));
}


@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
	return beanDefinition.getMetadata().isInterface();
}

我们也可以在其默认原有的过滤的基础上添加自己的过滤器:

// 添加包含过滤器
scanner.addIncludeFilter(typeFilter);
// 添加排除过滤器
scanner.addExcludeFilter(typeFilter);

而registerDefaultFilters的默认实现是:里面默认加入了一个Componet注解过滤器。

protected void registerDefaultFilters() {
	this.includeFilters.add(new AnnotationTypeFilter(Component.class));
	ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
	try {
		this.includeFilters.add(new AnnotationTypeFilter(
				((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
		logger.debug("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.
	}
	try {
		this.includeFilters.add(new AnnotationTypeFilter(
				((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
		logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
	}
	catch (ClassNotFoundException ex) {
		// JSR-330 API not available - simply skip.
	}
}

 

用法二:AnnotatedBeanDefinitionReader

register 用法是通过AnnotatedBeanDefinitionReader完成的:

public void register(Class<?>... annotatedClasses) {
    Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
    // 通过reader完成的
    this.reader.register(annotatedClasses);
}

AnnotatedBeanDefinitionReader#register

public void register(Class<?>... annotatedClasses) {
	for (Class<?> annotatedClass : annotatedClasses) {
		registerBean(annotatedClass);
	}
}

registerBean:

public void registerBean(Class<?> annotatedClass) {
	doRegisterBean(annotatedClass, null, null, null);
}


<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
		@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

	// 生成AnnotatedGenericBeanDefinition 相比 GenericBeanDefinition 多了个属性 AnnotationMetadata metadata;
	AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
	// 根据Conditional(按条件加载)注解判断是否需要被跳过
	if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
		return;
	}

	// 这里设置它的scope
	abd.setInstanceSupplier(instanceSupplier);
	ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
	abd.setScope(scopeMetadata.getScopeName());
	String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

	// 设置Primary, LazyInit, Qualifier属性
	AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
	if (qualifiers != null) {
		for (Class<? extends Annotation> qualifier : qualifiers) {
			if (Primary.class == qualifier) {
				abd.setPrimary(true);
			}
			else if (Lazy.class == qualifier) {
				abd.setLazyInit(true);
			}
			else {
				abd.addQualifier(new AutowireCandidateQualifier(qualifier));
			}
		}
	}
	for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
		customizer.customize(abd);
	}

	// 构建BeanDefinitionHolder进行注册
	BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
	// 如果有ScopedProxy的话处理ScopedProxy
	definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
	// 注册
	BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值