Spring源碼解析-基於註解依賴註入
阿新 • • 發佈:2017-10-28
上下文 owa necessary test processor 當前 dha count any
在spring2.5版本提供了註解的依賴註入功能,可以減少對xml配置。
主要使用的是
AnnotationConfigApplicationContext: 一個註解配置上下文
AutowiredAnnotationBeanPostProcessor: spring提供的用於這一目的的BeanPostProcessor實現,用來檢查當前對象是否有@Autowired標註的依賴註入。
項目中除了使用@Autowired之外,還可以選擇JSR250的一些註解例如@Resource大致和@Autowired相同。
CommonAnnotationBeanPostProcessor:JSR250也需要BeanPostProcessor,spring實現類了。
在spring配置文件中添加<context:annotation-config/>可以將這些processor添加到spring容器中。
另外使用註解的方式還需要一個classpath-scanning功能,使用這一功能只需要在配置文件中添加<context:component-scan base-package=‘com.xx.xx‘>
@Component註解使用太寬泛,細分了@Controller,@Service等標註。
簡單示例
@Component public class AnnotationDemo { public void printInfo(){ System.out.println(this.getClass()); } }
@Component public class AnnotationDemo2 { public void printInfo(){ System.out.println(this.getClass()); } }
測試類
@Test public void testAnnotationInject(){ ApplicationContext context = new AnnotationConfigApplicationContext("org.lzyer.test"); //指定某些類 //ApplicationContext context = new AnnotationConfigApplicationContext(AnnotationDemo.class,AnnotationDemo2.class); AnnotationDemo ad = context.getBean(AnnotationDemo.class); AnnotationDemo2 ad2 = context.getBean(AnnotationDemo2.class); ad.printInfo(); ad2.printInfo(); }
方式一為加載包下帶註解的類。方式二是指定某些類。
運行結果:
class org.lzyer.test.AnnotationDemo
class org.lzyer.test.AnnotationDemo2
註入流程
/** * Create a new AnnotationConfigApplicationContext, scanning for bean definitions * in the given packages and automatically refreshing the context. * @param basePackages the packages to check for annotated classes*/ public AnnotationConfigApplicationContext(String... basePackages) { this(); scan(basePackages);//掃描包 refresh();//調用AbstractApplicationContext中的refresh方法 }
/** * Perform a scan within the specified base packages. * @param basePackages the packages to check for annotated classes * @return number of beans registered */ public int scan(String... basePackages) { int beanCountAtScanStart = this.registry.getBeanDefinitionCount(); doScan(basePackages);//掃描 // Register annotation config processors, if necessary. if (this.includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart); }
/** * Perform a scan within the specified base packages, * returning the registered bean definitions. * <p>This method does <i>not</i> register an annotation config processor * but rather leaves this up to the caller. * @param basePackages the packages to check for annotated classes * @return set of beans registered if any for tooling registration purposes (never {@code null}) */ protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>(); for (String basePackage : basePackages) {//遍歷所有的包 Set<BeanDefinition> candidates = findCandidateComponents(basePackage);//查找候選組件 for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); registerBeanDefinition(definitionHolder, this.registry);//註冊beandefinition } } } return beanDefinitions; }
/** * Scan the class path for candidate components. * @param basePackage the package to check for annotated classes * @return a corresponding Set of autodetected bean definitions */ public Set<BeanDefinition> findCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>(); try { String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + "/" + this.resourcePattern;//補充路徑 Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (Resource resource : resources) {//遍歷Resource if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) { try {//通過asm獲取class,暫且不研究asm MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource); if (isCandidateComponent(metadataReader)) {//判斷是否為候選組件 ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); 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; }
查看2個判斷條件。
/** * Determine whether the given bean definition qualifies as candidate. * <p>The default implementation checks whether the class is concrete * (i.e. not abstract and not an interface). Can be overridden in subclasses. * @param beanDefinition the bean definition to check * @return whether the bean definition qualifies as a candidate component */ protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { return (beanDefinition.getMetadata().isConcrete() && beanDefinition.getMetadata().isIndependent()); }
進行匹配。
/** * Determine whether the given class does not match any exclude filter * and does match at least one include filter. * @param metadataReader the ASM ClassReader for the class * @return whether the class qualifies as a candidate component */ protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { for (TypeFilter tf : this.excludeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { return false; } } for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { return isConditionMatch(metadataReader); } } return false; }
@Override protected boolean matchSelf(MetadataReader metadataReader) { AnnotationMetadata metadata = metadataReader.getAnnotationMetadata(); return metadata.hasAnnotation(this.annotationType.getName()) || (this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName())); }
查看hasAnnotation和 hasMetaAnnotation方法。
@Override public boolean hasAnnotation(String annotationType) { return this.annotationSet.contains(annotationType); } @Override public boolean hasMetaAnnotation(String metaAnnotationType) { Collection<Set<String>> allMetaTypes = this.metaAnnotationMap.values(); for (Set<String> metaTypes : allMetaTypes) { if (metaTypes.contains(metaAnnotationType)) { return true; } } return false; }
annotationSet包含的是註解,
metaAnnotationMap的key為註解,value是一個set。
Spring源碼解析-基於註解依賴註入