Spring源码分析之@Component注解自动扫描的处理
前言
在项目中使用Spring,我们都会使用它的自动扫描Bean的功能,今天就来分析一下自动扫描的原理。
简单使用
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
public class TestComponentScan {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(
beanFactory, true);
String packageName = ClassUtils.getPackageName(TestComponentScan.class);
scanner.scan(packageName);
UserService userService = (UserService) beanFactory.getBean("userService");
userService.users();
}
@Component("userService")
public static class UserService {
public void users() {
System.out.println("UserService.users()");
}
}
}
使用ClassPathBeanDefinitionScanner(扫描器)来扫描指定package下的Bean,默认会扫描包含@Component注解的Class。
根据扫描到的Class创建BeanDefinition,并注册到BeanFactory中。我们也可以自定义要扫描的条件,如扫描指定的接口的实现类。
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.ClassUtils;
public class TestComponentScan2 {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(
beanFactory, true);
//扫描类型为IService的Class
scanner.addIncludeFilter(new ClassTypeFilter(IService.class));
String packageName = ClassUtils.getPackageName(TestComponentScan2.class);
scanner.scan(packageName);
Map<String, IService> iServiceMap = beanFactory.getBeansOfType(IService.class);
for (Entry<String, IService> entry : iServiceMap.entrySet()) {
System.out.println(entry);
}
}
public static class ClassTypeFilter implements TypeFilter {
private Class<?> targetType;
public ClassTypeFilter(Class<?> targetType) {
this.targetType = targetType;
}
@Override
public boolean match(MetadataReader metadataReader,
MetadataReaderFactory metadataReaderFactory) {
try {
//获取Class
Class<?> aClass = ClassUtils
.forName(metadataReader.getClassMetadata().getClassName(),
ClassUtils.getDefaultClassLoader());
return !metadataReader.getClassMetadata().isInterface() &&
targetType.isAssignableFrom(aClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return false;
}
}
public interface IService {
}
public static class AddressService {
}
public static class UserService implements IService {
public void users() {
System.out.println("UserService.users()");
}
}
}
扫描接口IService的实现类,只有UserService,不包含AddressService。SpringDataJPA就是通过这种方式来扫描Repository接口的。
源码分析
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
this.registry = registry;
//注册默认类型过滤器,过滤@Component注解
if (useDefaultFilters) {
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
开始扫描
public int scan(String... basePackages) {
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
//实际扫描
doScan(basePackages);
//注册一些处理注解相关的BeanPostProcessor
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
查看自动注册了哪些BeanPostProcessor
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
//获取DefaultListableBeanFactory,这个例子中registry的实际类型就是DefaultListableBeanFactory
//如果我们是在ApplicationContext中调用此方法,registry的类型就是ApplicationContext的具体实现类
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
//处理@Value注解的属性注入
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//处理@Configuration注解,@ComponentScan注解,@Bean注解等
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//处理@Autowired注解的属性注入
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
////支持@PostConstruct(Bean初始化)和@PreDestroy(Bean销毁)
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//处理JPA相关注解
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//处理@EventListener注解相关
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
//也是事件监听相关,暂时不管
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
真正扫描的过程
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
//保存扫描到的所有BeanDefinition
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
//扫描指定package下的所有class,根据类型过滤器过滤,根据Class创建BeanDefinition
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
//处理@Scope注解相关
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) {
//处理@Primary注解,@Lazy注解(是否懒加载)等
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
//@Scope注解可以配置对当前Bean是否创建动态代理
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//将BeanDefinition注册到BeanFactory中
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
继续跟进去findCandidateComponents()方法
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
//componentsIndex不知道是什么情况下使用,暂时不管
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
//真正扫描Class
return scanCandidateComponents(basePackage);
}
}
继续scanCandidateComponents()方法
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
//使用PathMatchingResourcePatternResolver(支持通配符)从classpath下查找所有class文件
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
//实际的查找路径为classpath*:xx/**/*.class
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
for (Resource resource : resources) {
if (resource.isReadable()) {
try {
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
//根据类型过滤器判断,如我们自己定义的ClassTypeFilter,其实这里还会根据@Conditional注解来判断,但先不管
if (isCandidateComponent(metadataReader)) {
//创建BeanDefinition
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
//当前Class必须是独立的(非内部类,或者是静态内部类)
if (isCandidateComponent(sbd)) {
candidates.add(sbd);
}
}
}
}
}
}
return candidates;
}
至此就扫描完了,总结起来就是查找到所有的class,根据类型过滤器来过滤,根据class创建BeanDefinition并注册到BeanFactory(实际上是BeanDefinitionRegistry类型)中。
Spring中的使用
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class BeanConfig {
}
我们使用Spring或者SpringBoot的时候,都是通过@ComponentScan注解来开启扫描的,不需要手动创建ClassPathBeanDefinitionScanner对象且调用scan()方法。
总结
@Controller注解,@Service,@Repository,这三个注解都是被@Component注解所标记的,Spring也会扫描到。