Spring 注解形式使用有下面两种方式
通过AnnotationConfigApplicationContext
参数:扫描包
通过 xml 配置context:component-scan
属性base-package
AnnotationConfigApplicationContext aac =
new AnnotationConfigApplicationContext ("com.huifer.source.spring.ann" );
<context : component-scan base-package =" com.huifer.source.spring.ann" >
</context : component-scan >
目标明确开始找入口方法
AnnotationConfigApplicationContext
直接点进去看就找到了
public AnnotationConfigApplicationContext (String ... basePackages ) {
this ();
// 扫描包
scan (basePackages );
refresh ();
}
context:component-scan
寻找方式:冒号:
钱+NamespaceHandler 或者全文搜索component-scan
,最终找到org.springframework.context.config.ContextNamespaceHandler
public class ContextNamespaceHandler extends NamespaceHandlerSupport {
@ Override
public void init () {
registerBeanDefinitionParser ("property-placeholder" , new PropertyPlaceholderBeanDefinitionParser ());
registerBeanDefinitionParser ("property-override" , new PropertyOverrideBeanDefinitionParser ());
registerBeanDefinitionParser ("annotation-config" , new AnnotationConfigBeanDefinitionParser ());
registerBeanDefinitionParser ("component-scan" , new ComponentScanBeanDefinitionParser ());
registerBeanDefinitionParser ("load-time-weaver" , new LoadTimeWeaverBeanDefinitionParser ());
registerBeanDefinitionParser ("spring-configured" , new SpringConfiguredBeanDefinitionParser ());
registerBeanDefinitionParser ("mbean-export" , new MBeanExportBeanDefinitionParser ());
registerBeanDefinitionParser ("mbean-server" , new MBeanServerBeanDefinitionParser ());
}
}
org.springframework.context.annotation.ComponentScanBeanDefinitionParser
实现BeanDefinitionParser
直接看parse
方法
@ Override
@ Nullable
public BeanDefinition parse (Element element , ParserContext parserContext ) {
// 获取 base-package 属性值
String basePackage = element .getAttribute (BASE_PACKAGE_ATTRIBUTE );
// 处理 ${}
basePackage = parserContext .getReaderContext ().getEnvironment ().resolvePlaceholders (basePackage );
// 分隔符`,;\t\n`切分
String [] basePackages = StringUtils .tokenizeToStringArray (basePackage ,
ConfigurableApplicationContext .CONFIG_LOCATION_DELIMITERS );
// Actually scan for bean definitions and register them.
// 扫描对象创建
ClassPathBeanDefinitionScanner scanner = configureScanner (parserContext , element );
// 执行扫描方法
Set <BeanDefinitionHolder > beanDefinitions = scanner .doScan (basePackages );
// 注册组件,触发监听
registerComponents (parserContext .getReaderContext (), beanDefinitions , element );
return null ;
}
回过头看AnnotationConfigApplicationContext
org.springframework.context.annotation.AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext (String ... basePackages ) {
this ();
// 扫描包
scan (basePackages );
refresh ();
}
private final ClassPathBeanDefinitionScanner scanner ;
@ Override
public void scan (String ... basePackages ) {
Assert .notEmpty (basePackages , "At least one base package must be specified" );
this .scanner .scan (basePackages );
}
org.springframework.context.annotation.ClassPathBeanDefinitionScanner.scan
public int scan (String ... basePackages ) {
// 获取bean数量
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 );
}
这个地方doScan
似曾相识,他就是org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse
中的doScan
,下一步解析 doScan
org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan
protected Set <BeanDefinitionHolder > doScan (String ... basePackages ) {
Assert .notEmpty (basePackages , "At least one base package must be specified" );
Set <BeanDefinitionHolder > beanDefinitions = new LinkedHashSet <>();
for (String basePackage : basePackages ) {
// 寻找组件
Set <BeanDefinition > candidates = findCandidateComponents (basePackage );
for (BeanDefinition candidate : candidates ) {
// bean 作用域设置
ScopeMetadata scopeMetadata = this .scopeMetadataResolver .resolveScopeMetadata (candidate );
// 设置生命周期
candidate .setScope (scopeMetadata .getScopeName ());
// 创建beanName
String beanName = this .beanNameGenerator .generateBeanName (candidate , this .registry );
if (candidate instanceof AbstractBeanDefinition ) {
// 设置默认属性 具体方法:org.springframework.beans.factory.support.AbstractBeanDefinition.applyDefaults
postProcessBeanDefinition ((AbstractBeanDefinition ) candidate , beanName );
}
if (candidate instanceof AnnotatedBeanDefinition ) {
// 读取Lazy,Primary 等注解
AnnotationConfigUtils .processCommonDefinitionAnnotations ((AnnotatedBeanDefinition ) candidate );
}
// bean的重复检查
if (checkCandidate (beanName , candidate )) {
// 创建 BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder (candidate , beanName );
// 代理对象的处理
definitionHolder =
AnnotationConfigUtils .applyScopedProxyMode (scopeMetadata , definitionHolder , this .registry );
// 放入list中,最后返回用
beanDefinitions .add (definitionHolder );
// 注册bean
registerBeanDefinition (definitionHolder , this .registry );
}
}
}
return beanDefinitions ;
}
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents
public Set <BeanDefinition > findCandidateComponents (String basePackage ) {
// 扫描
if (this .componentsIndex != null && indexSupportsIncludeFilters ()) {
return addCandidateComponentsFromIndex (this .componentsIndex , basePackage );
}
else {
return scanCandidateComponents (basePackage );
}
}
/**
* 扫描当前包路径下的资源
* @param basePackage
* @return
*/
private Set <BeanDefinition > scanCandidateComponents (String basePackage ) {
Set <BeanDefinition > candidates = new LinkedHashSet <>();
try {
// 字符串拼接出一个编译后的路径 classpath://
// 这里替换了通配符
String packageSearchPath = ResourcePatternResolver .CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage (basePackage ) + '/' + this .resourcePattern ;
// 获取资源
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
MetadataReader metadataReader = getMetadataReaderFactory ().getMetadataReader (resource );
// 判断是否是 Component
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 ;
}
org.springframework.context.annotation.ScopeMetadataResolver#resolveScopeMetadata
/**
* 生命周期设置
*
* @param definition the target bean definition
* @return
*/
@ Override
public ScopeMetadata resolveScopeMetadata (BeanDefinition definition ) {
ScopeMetadata metadata = new ScopeMetadata ();
// 判断是否属于 AnnotatedBeanDefinition
if (definition instanceof AnnotatedBeanDefinition ) {
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition ) definition ;
AnnotationAttributes attributes = AnnotationConfigUtils .attributesFor (
annDef .getMetadata (), this .scopeAnnotationType );
if (attributes != null ) {
// 获取 value 属性值并且设置
metadata .setScopeName (attributes .getString ("value" ));
// 获取 proxyMode 属性值并且设置
ScopedProxyMode proxyMode = attributes .getEnum ("proxyMode" );
if (proxyMode == ScopedProxyMode .DEFAULT ) {
proxyMode = this .defaultProxyMode ;
}
metadata .setScopedProxyMode (proxyMode );
}
}
return metadata ;
}
org.springframework.context.annotation.AnnotationScopeMetadataResolverTests#resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation
测试用例
@ Test
public void resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation () {
AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition (AnnotatedWithScopedProxy .class );
ScopeMetadata scopeMetadata = this .scopeMetadataResolver .resolveScopeMetadata (bd );
assertNotNull ("resolveScopeMetadata(..) must *never* return null." , scopeMetadata );
assertEquals ("request" , scopeMetadata .getScopeName ());
assertEquals (TARGET_CLASS , scopeMetadata .getScopedProxyMode ());
}
org.springframework.beans.factory.support.BeanNameGenerator#generateBeanName
创建 beanName org.springframework.context.annotation.AnnotationBeanNameGenerator#generateBeanName
@ Override
public String generateBeanName (BeanDefinition definition , BeanDefinitionRegistry registry ) {
if (definition instanceof AnnotatedBeanDefinition ) {
// 如果存在bean(value="") value存在
String beanName = determineBeanNameFromAnnotation ((AnnotatedBeanDefinition ) definition );
if (StringUtils .hasText (beanName )) {
// Explicit bean name found.
return beanName ;
}
}
// Fallback: generate a unique default bean name.
// 创建beanName
return buildDefaultBeanName (definition , registry );
}
@ Nullable
protected String determineBeanNameFromAnnotation (AnnotatedBeanDefinition annotatedDef ) {
AnnotationMetadata amd = annotatedDef .getMetadata ();
Set <String > types = amd .getAnnotationTypes ();
String beanName = null ;
for (String type : types ) {
AnnotationAttributes attributes = AnnotationConfigUtils .attributesFor (amd , type );
if (attributes != null && isStereotypeWithNameValue (type , amd .getMetaAnnotationTypes (type ), attributes )) {
// 获取注解的value 属性值
Object value = attributes .get ("value" );
if (value instanceof String ) {
String strVal = (String ) value ;
// 判断是否存在值
if (StringUtils .hasLength (strVal )) {
if (beanName != null && !strVal .equals (beanName )) {
throw new IllegalStateException ("Stereotype annotations suggest inconsistent " +
"component names: '" + beanName + "' versus '" + strVal + "'" );
}
// beanName = value属性值
beanName = strVal ;
}
}
}
}
return beanName ;
}
@ Service (value = "dhc" )
public class DemoService {
}
org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.support.BeanDefinitionRegistry)
org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition)
protected String buildDefaultBeanName (BeanDefinition definition ) {
// 获取bean class name
String beanClassName = definition .getBeanClassName ();
Assert .state (beanClassName != null , "No bean class name set" );
// 获取短类名,
String shortClassName = ClassUtils .getShortName (beanClassName );
// 第一个字母小写
return Introspector .decapitalize (shortClassName );
}
@ Configuration
public class BeanConfig {
@ Scope (value =ConfigurableBeanFactory .SCOPE_PROTOTYPE )
@ Bean (value = "hc" )
public Ubean f () {
return new Ubean ();
}
}
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#postProcessBeanDefinition
protected void postProcessBeanDefinition (AbstractBeanDefinition beanDefinition , String beanName ) {
beanDefinition .applyDefaults (this .beanDefinitionDefaults );
if (this .autowireCandidatePatterns != null ) {
beanDefinition .setAutowireCandidate (PatternMatchUtils .simpleMatch (this .autowireCandidatePatterns , beanName ));
}
}
public void applyDefaults (BeanDefinitionDefaults defaults ) {
setLazyInit (defaults .isLazyInit ());
setAutowireMode (defaults .getAutowireMode ());
setDependencyCheck (defaults .getDependencyCheck ());
setInitMethodName (defaults .getInitMethodName ());
setEnforceInitMethod (false );
setDestroyMethodName (defaults .getDestroyMethodName ());
setEnforceDestroyMethod (false );
}
org.springframework.context.annotation.AnnotationConfigUtils#processCommonDefinitionAnnotations(org.springframework.beans.factory.annotation.AnnotatedBeanDefinition)
public static void processCommonDefinitionAnnotations (AnnotatedBeanDefinition abd ) {
processCommonDefinitionAnnotations (abd , abd .getMetadata ());
}
static void processCommonDefinitionAnnotations (AnnotatedBeanDefinition abd , AnnotatedTypeMetadata metadata ) {
// 获取 lazy 注解
AnnotationAttributes lazy = attributesFor (metadata , Lazy .class );
if (lazy != null ) {
abd .setLazyInit (lazy .getBoolean ("value" ));
} else if (abd .getMetadata () != metadata ) {
lazy = attributesFor (abd .getMetadata (), Lazy .class );
if (lazy != null ) {
abd .setLazyInit (lazy .getBoolean ("value" ));
}
}
if (metadata .isAnnotated (Primary .class .getName ())) {
abd .setPrimary (true );
}
AnnotationAttributes dependsOn = attributesFor (metadata , DependsOn .class );
if (dependsOn != null ) {
abd .setDependsOn (dependsOn .getStringArray ("value" ));
}
AnnotationAttributes role = attributesFor (metadata , Role .class );
if (role != null ) {
abd .setRole (role .getNumber ("value" ).intValue ());
}
AnnotationAttributes description = attributesFor (metadata , Description .class );
if (description != null ) {
abd .setDescription (description .getString ("value" ));
}
}
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#checkCandidate
protected boolean checkCandidate (String beanName , BeanDefinition beanDefinition ) throws IllegalStateException {
// 判断当前 beanName 是否在注册表中
if (!this .registry .containsBeanDefinition (beanName )) {
return true ;
}
// 从注册表中获取
BeanDefinition existingDef = this .registry .getBeanDefinition (beanName );
// 当前的bean
BeanDefinition originatingDef = existingDef .getOriginatingBeanDefinition ();
if (originatingDef != null ) {
existingDef = originatingDef ;
}
if (isCompatible (beanDefinition , existingDef )) {
return false ;
}
throw new ConflictingBeanDefinitionException ("Annotation-specified bean name '" + beanName +
"' for bean class [" + beanDefinition .getBeanClassName () + "] conflicts with existing, " +
"non-compatible bean definition of same name and class [" + existingDef .getBeanClassName () + "]" );
}
org.springframework.context.annotation.AnnotationConfigUtils#applyScopedProxyMode
static BeanDefinitionHolder applyScopedProxyMode (
ScopeMetadata metadata , BeanDefinitionHolder definition , BeanDefinitionRegistry registry ) {
ScopedProxyMode scopedProxyMode = metadata .getScopedProxyMode ();
if (scopedProxyMode .equals (ScopedProxyMode .NO )) {
return definition ;
}
boolean proxyTargetClass = scopedProxyMode .equals (ScopedProxyMode .TARGET_CLASS );
// 创建代理对象
return ScopedProxyCreator .createScopedProxy (definition , registry , proxyTargetClass );
}