SpringIOC——scan()
闲时研究一下spring源码,一点一点的来。spring版本:5.2.4
一、构建spring源码环境
① spring的源码在github中,右上角fork一个分支到自己的github,然后直接git clone拉代码到本地。
② 改阿里云镜像
// build.gradle和settings.gradle文件中repositories下加入镜像,放到首位 maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
③ 导入gradle项目到idea中
PS:我下载的最新源码默认Gradle5.6.4,但是本地idea2018.1版本不兼容,建议下载最新版idea,然后破解
第一次构建spring源码环境,发现源码中有好多测试案例,有点惭愧平时工作中很少写测试案例。
二、IOC容器初始化的过程
选取SpringBoot默认启动类AnnotationConfigApplicationContext作为研究对象。
取对应测试案例类AnnotationConfigApplicationContextTests.java中的一个栗子:
@Test void scanAndRefresh() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.scan("org.springframework.context.annotation6"); context.refresh(); context.getBean(uncapitalize(ConfigForScanning.class.getSimpleName())); context.getBean("testBean"); // contributed by ConfigForScanning context.getBean(uncapitalize(ComponentForScanning.class.getSimpleName())); context.getBean(uncapitalize(Jsr330NamedForScanning.class.getSimpleName())); Map<String, Object> beans = context.getBeansWithAnnotation(Configuration.class); assertThat(beans).hasSize(1); }
1、AnnotationConfigApplicationContex Context = new AnnotationConfigApplication();
/* AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();*/ //初始化reader,手动装配reader.register(classes),reader.registry = this //初始化scannner,自动装配scanner.scan(packages),scanner.registry = this public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); } //父类初始化BeanFactory,IOC容器实质:DefaultListableBeanFactory public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory(); } //初始化一个资源配置器, new PathMatchingResourcePatternResolver public AbstractApplicationContext() { this.resourcePatternResolver = getResourcePatternResolver(); }
2、context.scan("org.springframework.context.annotation6"):自动装配指定路径下的bean
/* context.scan("org.springframework.context.annotation6"); */ /* AnnotationConfigApplicationContext.java */ public void scan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); this.scanner.scan(basePackages); } /* ClassPathBeanDefinitionScanner.java */ public int scan(String... basePackages) { int beanCountAtScanStart = this.registry.getBeanDefinitionCount(); //自动扫描basePackages下的bean,并装载 doScan(basePackages); // 注册注解有关规范的处理器 if (this.includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } //返回本次自动装配bean的数量 return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart); }
doScan(basePackages):
/* org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java */ 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) { //将指定basePackage下每个class初始化一个对应BeanDefinition实例,返回实例的集合 Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); //默认scopeMetadata.scopeName = singleton 对应Scope注解的value //默认scopeMetadate.scopeProxyMode = no 对应Scope注解的proxyMode candidate.setScope(scopeMetadata.getScopeName()); //此时beandefinition只有三个属性beanClass scope metedata //beanName生成器根据注解中value生成beanName,value为空则根据beanClass生成beanName //首字母+第二字母都是大写字母:直接返回例如AA.class beanName = AA //其他首字母变小写例如Aa.class beanName = aa String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { //设置一些默认属性 //autowireMode = 0 //dependencyCheck = 0 //initMethodName = 0 //enforceInitMethode = false //destroyMethodName = null //enforceDestroyMethod = false //beanName简单校验正则校验,一般beandefinition.autowiredCandidate = true; postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { //从metadate中获取并设置一些通用属性 //lazyinit:取自lazy注解value,默认null //primary:有primary注解true,不注解默认false //dependsOn:取自dependsOn注解value,默认null //role:取自role注解value,默认0 //description:取自description注解value,默认null AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, candidate)) { //BeanDefintionHolder={beanName = "",beanDefintion = "",aliases = ""} BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); //根据scopeMetadate.scopeProxyMode属性决定 //ScopedProxyMode.DEFAULT/NO:不创建代理类 //ScopedProxyMode.INTERFACES:JDK动态代理创建代理类 //ScopedProxyMode.TARGET_CLASS:CGLib创建代理类 //如果需要生成代理类,会registerBeanDefinition(targetBean,beanfactory) //下面就是registerBeanDefinition(proxyBean,beanfactory) definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
Set<BeanDefinition> candidates = findCandidateComponents(basePackage):读入对应package下class文件
/* org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java */ private Set<BeanDefinition> scanCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<>(); try { //packageSearchPath = classpath*:basePackage/**/*.class String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); //resources: //D:/myGItHub/spring-framework/spring-context/build/classes/java/test/org/springframework/context/annotation6/ComponentForScanning.class for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) { try { MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); //excludeFilters:过滤器,符合excludeFilters条件的,返回false,不生成BeanDefinition,不初始化bean //includeFilters:过滤器,符合includeFilters条件的,返回true,生成BeanDefinition,初始化bean, //另includeFilters:默认包含三个注解,常见的@Component、 //不常见的: //@ManagedBean : javax.annotation.ManagedBean //@Named : javax.inject.Named 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; }
registerBeanDefinition(definitionHolder, this.registry);注册beandefinition到beanfactory的容器中
/* org/springframework/beans/factory/support/DefaultListableBeanFactory.java:901 */ public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) { try { //beandefinition校验 //① 不能将工厂方法和容器生成方法重写结合起来用,factory必须创建具体实例 //② beanClass instanceof Class时,校验重写与重载方法 ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); //beandefinition已经存在时 if (existingDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { //如果不允许覆盖,抛出异常 throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } else if (existingDefinition.getRole() < beanDefinition.getRole()) { //role有三种角色 =0:application =1:support =2:infrastructure //newbean角色高于oldbean时log // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (logger.isInfoEnabled()) { logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else if (!beanDefinition.equals(existingDefinition)) { //newbean = oldbean log if (logger.isDebugEnabled()) { logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else { if (logger.isTraceEnabled()) { logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } //newbean覆盖oldbean this.beanDefinitionMap.put(beanName, beanDefinition); } //beandefinition不存在 else { if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) //已经有bean被实例化的情况下refresh()或getBean()之后 //再进行bean注册(register/scan)操作,无法判断多线程还是单线程,加锁规避多线程场景 synchronized (this.beanDefinitionMap) { //bean加入到beanfactory的bean容器beandefinitionMap中, //beanDefinitionMap是ConcurrentHashMap类型put操作是线程安全的 //但beandefinitionNames是ArrayList类型add操作时非线程安全的 this.beanDefinitionMap.put(beanName, beanDefinition); //既然用到了写时复制策略为什么不用CopyOnWriteArrayList //① 应该是性能需求吧,写时复制会导致内存消耗 //② 这里的写时复制策略主要是规避fast-fail,实现fast-safe List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; //删除已创建单例的beanName的容器ManualSingletonName中的beanName removeManualSingletonName(beanName); } } else { // Still in startup registration phase //初次启动容器时单线程 this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName); removeManualSingletonName(beanName); } this.frozenBeanDefinitionNames = null; } if (existingDefinition != null || containsSingleton(beanName)) { //重新设置相关的beandefinition 子类等 resetBeanDefinition(beanName); } }