目录
用法: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);
}