SpringBean

Spring扫描配置过程

当我们在Spring中指定component-scan之后,由ComponentScanBeanDefinitionParser将指定的xml装载成BeanDefinition,当然最终实现功能的还是ComponentScanBeanDefinitionScanner的doScan方法,ComponentScanBeanDefinitionParser的parse方法只是将配置文件写的包名转换为相对地址,然后由doScan方法执行装配任务

ComponentScanBeanDefinitionParser.java

@Nullable
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        String basePackage = element.getAttribute("base-package");
        basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
        String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ",; \t\n");
        ClassPathBeanDefinitionScanner scanner = this.configureScanner(parserContext, element);
        Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
        this.registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
        return null;
    }

ComponentScanBeanDefinitionScanner.java

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);
            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);
                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);
                }
            }
        }

        return beanDefinitions;
    }

Bean的创建过程

1.实例化:当客户端向容器申请一个Bean时或者当容器在初始化一个Bean发现还需要依赖另一个Bean时,会将扫描到的信息以BeanDefinition的形式保存,使用BeanDefinition来实例化对应的Bean。

2.设置对象属性注入(这里涉及到循环依赖问题):Spring通过BeanDefinition找到对象所依赖的其他对象,并将这个对象一并创建赋值

3.处理Aware接口:Spring会检测实例化的这个类是否有实现Aware接口,如果实现了则去调用相对应的方法,例如常见的BeanNameAware、BeanClassLoader、BeanFactory、ApplicationContextAware

4.BeanPostProcessor前置处理:当Bean实现BeanPostProcessor接口时,并重写了postProcessorBeforInitialization则会去调用这个方法

5.InitializingBean:Spring检测如果实现了该接口,则会调用afterPropertiesSet方法,制定初始化逻辑

6.init-method:或者@PostConstruct注解,如果Spring发现Bean配置了该属性或者注解,那么就会去调用这个方法,执行该方法的初始化逻辑。

7.BeanPostProcessor后置处理:当Bean实现BeanPostProcessor接口时,并重写了postProcessorAfterInitialization则会去调用这个方法


这时Bean就已经创建完成了


8.DisposableBean:当Bean实现了这个接口,在对象销毁前就会调用该方法

9.destroy-method:或者@PreDestroy注解,如果Spring发现Bean配置了该属性或者注解,那么就会去调用这个方法,执行该方法的销毁逻辑。

循环依赖问题

当A依赖B,B依赖A的时候,发生循环依赖问题,如果对于依赖注入时,使用的是构造器来注入的,那么可以使用@Lazy注解,来延迟加载,这样就可以在单例池中顺利创建。

而如果使用的@Autowired注解,那么Spring就直接帮我们解决这个问题,使用了三级缓存解决的这个问题。

首先先分析一下,当循环依赖发生的时候,单例池都没有相关的对象,且无法去直接new出来,那么就有了二级缓存,假如要创建一个A对象,但是单例池中没有对象B,那么就在二级缓存当中创建一个属性都为空的B对象,并把这个B注入到A中,此时单例池中就有了A对象,那么对象B就能直接创建了,这个时候A对象中的B属性就会被关联到单例池中的B,两个对象就创建完成。

二级缓存只能解决普通对象的循环依赖,如果循环依赖的是一个有AOP切面的对象,如果还是这种二级缓存模型则无法将对象的代理对象创建出来,则引入了三级缓存,如果发生循环依赖且在单例池和二级缓存都找不到时,则去三级缓存查找是否有对应的AOP配置信息对象,如果查找到则去将这个对象提前进行AOP,然后将这个代理对象放入二级缓存,这个配置信息则从三级缓存中删除。

private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);//单例池
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);//三级缓存
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16);//二级缓存

@Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                synchronized(this.singletonObjects) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        singletonObject = this.earlySingletonObjects.get(beanName);
                        if (singletonObject == null) {
                            ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                            if (singletonFactory != null) {
                                singletonObject = singletonFactory.getObject();
                                this.earlySingletonObjects.put(beanName, singletonObject);
                                this.singletonFactories.remove(beanName);
                            }
                        }
                    }
                }
            }
        }

        return singletonObject;
    }

image-20210828222853181

posted @ 2021-08-28 23:34  海杰wrangle  阅读(106)  评论(0编辑  收藏  举报