spring @Component原理及自定义实现
@Component 原理
@Component扫描注册调用栈
# ClassPathBeanDefinitionScanner类
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:280)
# ComponentScanAnnotationParser类
at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:128)
# ConfigurationClassParser类
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:296)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:175)
# ConfigurationClassPostProcessor类
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:331)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247)
# PostProcessorRegistrationDelegate类
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112)
# AbstractApplicationContext类
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
- locked <0xe7b> (a java.lang.Object)
# ServletWebServerApplicationContext类
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
# SpringApplication类
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
# 项目启动入口
at com.example.demo.DemoApplication.main(DemoApplication.java:16)
ComponentScan
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
@AliasFor("basePackages")
String[] value() default {}; //指定扫描的包
@AliasFor("value")
String[] basePackages() default {}; //与value等效
Class<?>[] basePackageClasses() default {}; //指定扫描的类
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
//指定beanName生成器
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
String resourcePattern() default "**/*.class";
boolean useDefaultFilters() default true; //是否使用默认的过滤器
ComponentScan.Filter[] includeFilters() default {}; //包含的过滤器
ComponentScan.Filter[] excludeFilters() default {}; //排除的过滤器
boolean lazyInit() default false;
@Retention(RetentionPolicy.RUNTIME)
@Target({})
public @interface Filter {
FilterType type() default FilterType.ANNOTATION; //默认注解过滤
@AliasFor("classes")
Class<?>[] value() default {}; //可以设置自定义过滤器
@AliasFor("value")
Class<?>[] classes() default {};
String[] pattern() default {};
}
}
FilterType
public enum FilterType {
ANNOTATION, //指定的注解类(可以是自定义的注解类)
ASSIGNABLE_TYPE, //过滤指定的类
ASPECTJ, //aspectJ表达式
REGEX, //正则表达式
CUSTOM; //自定义过滤器(自定义匹配规则)
private FilterType() {
}
}
TypeFilter:实现该接口,可自定义过滤匹配规则
@FunctionalInterface
public interface TypeFilter {
boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException;
}
@ComponentScan使用示例
@ComponentScan(includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {CustomComponent.class}),
//标注了@CustomComponent注解的类会被注册
@ComponentScan.Filter(type = FilterType.REGEX, pattern = "com.example.demo.service..*"),
//扫描注册正则表达式匹配的类
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {CustomFilter.class}),
//自定义类过滤器,匹配的类会被扫描注册
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {HelloServiceImpl.class})
//扫描注册指定的类
})
ComponentScanParser:根据@ComponentScan注解扫描注册类
class ComponentScanAnnotationParser {
private final Environment environment;
private final ResourceLoader resourceLoader;
private final BeanNameGenerator beanNameGenerator;
private final BeanDefinitionRegistry registry;
public ComponentScanAnnotationParser(Environment environment, ResourceLoader resourceLoader, BeanNameGenerator beanNameGenerator, BeanDefinitionRegistry registry) {
this.environment = environment;
this.resourceLoader = resourceLoader;
this.beanNameGenerator = beanNameGenerator;
this.registry = registry;
}
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, String declaringClass) {
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = BeanNameGenerator.class == generatorClass;
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : (BeanNameGenerator)BeanUtils.instantiateClass(generatorClass));
//设置beanName生成器
ScopedProxyMode scopedProxyMode = (ScopedProxyMode)componentScan.getEnum("scopedProxy");
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
scanner.setScopedProxyMode(scopedProxyMode);
} else {
Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
scanner.setScopeMetadataResolver((ScopeMetadataResolver)BeanUtils.instantiateClass(resolverClass));
}
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
AnnotationAttributes[] var15 = componentScan.getAnnotationArray("includeFilters");
int var8 = var15.length;
int var9;
AnnotationAttributes excludeFilterAttributes;
List typeFilters;
Iterator var12;
TypeFilter typeFilter;
for(var9 = 0; var9 < var8; ++var9) {
excludeFilterAttributes = var15[var9];
typeFilters = TypeFilterUtils.createTypeFiltersFor(excludeFilterAttributes, this.environment, this.resourceLoader, this.registry);
var12 = typeFilters.iterator();
while(var12.hasNext()) {
typeFilter = (TypeFilter)var12.next();
scanner.addIncludeFilter(typeFilter);
} //添加include过滤器
}
var15 = componentScan.getAnnotationArray("excludeFilters");
var8 = var15.length;
for(var9 = 0; var9 < var8; ++var9) {
excludeFilterAttributes = var15[var9];
typeFilters = TypeFilterUtils.createTypeFiltersFor(excludeFilterAttributes, this.environment, this.resourceLoader, this.registry);
var12 = typeFilters.iterator();
while(var12.hasNext()) {
typeFilter = (TypeFilter)var12.next();
scanner.addExcludeFilter(typeFilter);
} //添加exclude过滤器
}
boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
scanner.getBeanDefinitionDefaults().setLazyInit(true);
}
Set<String> basePackages = new LinkedHashSet();
String[] basePackagesArray = componentScan.getStringArray("basePackages");
String[] var19 = basePackagesArray;
int var21 = basePackagesArray.length;
int var22;
for(var22 = 0; var22 < var21; ++var22) {
String pkg = var19[var22];
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg), ",; \t\n");
Collections.addAll(basePackages, tokenized);
}
Class[] var20 = componentScan.getClassArray("basePackageClasses");
var21 = var20.length;
for(var22 = 0; var22 < var21; ++var22) {
Class<?> clazz = var20[var22];
basePackages.add(ClassUtils.getPackageName(clazz));
}
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
protected boolean matchClassName(String className) {
return declaringClass.equals(className);
}
});
return scanner.doScan(StringUtils.toStringArray(basePackages));
} //扫描指定的包
}
ClassPathBeanDefinitionScanner:扫描注册beanDefinition
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
private final BeanDefinitionRegistry registry;
private BeanDefinitionDefaults beanDefinitionDefaults;
@Nullable
private String[] autowireCandidatePatterns;
private BeanNameGenerator beanNameGenerator;
private ScopeMetadataResolver scopeMetadataResolver;
private boolean includeAnnotationConfig;
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment) {
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @Nullable ResourceLoader resourceLoader) {
public final BeanDefinitionRegistry getRegistry() {
public BeanDefinitionDefaults getBeanDefinitionDefaults() {
public void setBeanDefinitionDefaults(@Nullable BeanDefinitionDefaults beanDefinitionDefaults) {
public void setAutowireCandidatePatterns(@Nullable String... autowireCandidatePatterns) {
public void setScopeMetadataResolver(@Nullable ScopeMetadataResolver scopeMetadataResolver) {
public void setScopedProxyMode(ScopedProxyMode scopedProxyMode) {
public void setIncludeAnnotationConfig(boolean includeAnnotationConfig) {
public void setBeanNameGenerator(@Nullable BeanNameGenerator beanNameGenerator) {
public int scan(String... basePackages) { //扫描指定目录包下的类
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
this.doScan(basePackages); //执行具体扫描操作
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return this.registry.getBeanDefinitionCount() - beanCountAtScanStart;
}
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet();
String[] var3 = basePackages;
int var4 = basePackages.length;
for(int var5 = 0; var5 < var4; ++var5) {
String basePackage = var3[var5];
Set<BeanDefinition> candidates = this.findCandidateComponents(basePackage);
//查找component注解类
Iterator var8 = candidates.iterator();
while(var8.hasNext()) {
BeanDefinition candidate = (BeanDefinition)var8.next();
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
//生成beanName,后续用来注册bean
if (candidate instanceof AbstractBeanDefinition) {
this.postProcessBeanDefinition((AbstractBeanDefinition)candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)candidate);
}
if (this.checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
this.registerBeanDefinition(definitionHolder, this.registry);
} //注册bean信息
}
}
return beanDefinitions;
}
protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
protected boolean isCompatible(BeanDefinition newDefinition, BeanDefinition existingDefinition) {
private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
AnnotationBeanNameGenerator:注解标注的类生成beanName
public class AnnotationBeanNameGenerator implements BeanNameGenerator {
public static final AnnotationBeanNameGenerator INSTANCE = new AnnotationBeanNameGenerator();
private static final String COMPONENT_ANNOTATION_CLASSNAME = "org.springframework.stereotype.Component";
private final Map<String, Set<String>> metaAnnotationTypesCache = new ConcurrentHashMap();
public AnnotationBeanNameGenerator() {
}
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
if (definition instanceof AnnotatedBeanDefinition) { //如果是注解标注的类
String beanName = this.determineBeanNameFromAnnotation((AnnotatedBeanDefinition)definition);
//生成beanName
if (StringUtils.hasText(beanName)) {
return beanName;
} //如果注解中设置了value(beanname),且不为空,则直接返回
}
return this.buildDefaultBeanName(definition, registry);
//如果没有设置,通过类名获取beanName
}
@Nullable
protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
AnnotationMetadata amd = annotatedDef.getMetadata();
Set<String> types = amd.getAnnotationTypes();
String beanName = null;
Iterator var5 = types.iterator();
while(var5.hasNext()) {
String type = (String)var5.next();
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
if (attributes != null) {
Set<String> metaTypes = (Set)this.metaAnnotationTypesCache.computeIfAbsent(type, (key) -> {
Set<String> result = amd.getMetaAnnotationTypes(key);
return result.isEmpty() ? Collections.emptySet() : result;
});
if (this.isStereotypeWithNameValue(type, metaTypes, attributes)) {
Object value = attributes.get("value"); //读取注解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 = strVal;
}
}
}
}
}
return beanName;
}
protected boolean isStereotypeWithNameValue(String annotationType, Set<String> metaAnnotationTypes, @Nullable Map<String, Object> attributes) {
boolean isStereotype = annotationType.equals("org.springframework.stereotype.Component") || metaAnnotationTypes.contains("org.springframework.stereotype.Component") || annotationType.equals("javax.annotation.ManagedBean") || annotationType.equals("javax.inject.Named");
return isStereotype && attributes != null && attributes.containsKey("value");
}
protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return this.buildDefaultBeanName(definition);
}
protected String buildDefaultBeanName(BeanDefinition definition) {
String beanClassName = definition.getBeanClassName();
Assert.state(beanClassName != null, "No bean class name set");
String shortClassName = ClassUtils.getShortName(beanClassName);
return Introspector.decapitalize(shortClassName);
} //截取类名获取beanName
}
自定义注解
CustomComponent
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomComponent {
String value() default "";
}
HelloService
public interface HelloService {
String hello();
}
HelloServiceImpl
@CustomComponent
public class HelloServiceImpl implements HelloService {
@Override
public String hello() {
return "hello";
}
}
HelloController
@RestController
public class HelloController {
@Resource
private HelloService helloService;
@RequestMapping("/hello")
public String hello(){
System.out.println(helloService.hello());
return "hello";
}
}
DemoApplication
@SpringBootApplication
@ComponentScan(includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {CustomComponent.class})
}) //设置自定义注解
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
localhost:8080/hello:启动应用,控制台输出
2022-04-27 19:18:13.847 INFO 5271 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 787 ms
2022-04-27 19:18:14.126 INFO 5271 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-04-27 19:18:14.134 INFO 5271 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 1.412 seconds (JVM running for 1.837)
2022-04-27 19:18:16.373 INFO 5271 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-04-27 19:18:16.373 INFO 5271 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2022-04-27 19:18:16.374 INFO 5271 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
hello