Spring源码分析(三)registerBean方法分析

原创 吴就业 79 0 2018-10-29

本文为博主原创文章,未经博主允许不得转载。

本文链接:https://www.wujiuye.com/article/5993092f019f4d68ac0a1d32f8d86ba4

作者:吴就业
链接:https://www.wujiuye.com/article/5993092f019f4d68ac0a1d32f8d86ba4
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。

补充一句,上一篇bean的创建过程在bean实例化之后为属性赋值是使用BeanUtils这个工具类来完成的,可以学一下BeanUtils的使用。

bean准备阶段

01

编写一个配置类:SpringConfig.java(所在包:wjy.stu.config),使用@Configuration注解。

02

编写bean类:UserBean、ScoreBean(所在包:wjy.stu.bean)使用@Component注解,

UserDao(所在包wjy.stu.dao)使用@Repository注解

03

在配置类SpringConfig.java上添加注解

@ComponentScans(
        {
                @ComponentScan("wjy.stu.bean"),
                @ComponentScan("wjy.stu.dao")
        }
)

04

编写一个BeanFactoryPostProcessor:MyBeanFactoryPostProcessor,实现postProcessBeanFactory方法打印bean工厂中所有的bean的名称。

@Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        String[] names = beanFactory.getBeanDefinitionNames();
        // 获取了所有的bean名称列表
        for(int i=0; i<names.length; i++){
            String name = names[i];
            BeanDefinition bd = beanFactory.getBeanDefinition(name);
            System.out.println(name + " bean properties: \n" + bd.getPropertyValues().toString());
        }
    }

05

编写一个BeanPostProcessor:MyBeanPostProcessor,实现接口中的方法。

@Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization==>" + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization==>" + beanName);
        return bean;
    }

06

在配置类SpringConfig.java上添加

 @Import({MyBeanFactoryPostProcessor.class, MyBeanPostProcessor.class})

07

在main方法中使用AnnotationConfigApplicationContext启动spring容器

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);

AnnotationConfigApplicationContext工作流程

分两步分析:

本篇先介绍registerBean方法内部执行流程分析

01

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        this();
        register(annotatedClasses);
        refresh();
}

02

实例化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner。

public AnnotationConfigApplicationContext() {
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
}

03

父类GenericApplicationContext的构造方法

public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
}

04

AnnotationConfigApplicationContext实现
AnnotationConfigRegistry接口的register方法
public void register(Class<?>... annotatedClasses) {
    this.reader.register(annotatedClasses);
}

05

AnnotationConfigApplicationContext的register方法最后调用的是AnnotatedBeanDefinitionReader类的register方法

【AnnotatedBeanDefinitionReader类】
public void register(Class<?>... annotatedClasses) {
        for (Class<?> annotatedClass : annotatedClasses) {
            registerBean(annotatedClass);
        }
}

06

最终调用 AnnotatedBeanDefinitionReader::registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>… qualifiers)方法完成bean的注册。

registerBean方法内部执行流程分析:

分析AnnotatedBeanDefinitionReader类的registerBean方法。

01

根据annotatedClass构造一个BeanDefinition

AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);

AnnotatedGenericBeanDefinition的构造方法

public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
        setBeanClass(beanClass);
        this.metadata = new StandardAnnotationMetadata(beanClass, true);
    }

StandardAnnotationMetadata类:

在StandardAnnotationMetadata构造方法中获取了这个bean的Class对象上的所有注解

public StandardAnnotationMetadata(Class<?> introspectedClass, boolean nestedAnnotationsAsMap) {
        super(introspectedClass);
        this.annotations = introspectedClass.getAnnotations();
        this.nestedAnnotationsAsMap = nestedAnnotationsAsMap;
    }

02

获取scope元数据,即描述scope的数据,scope信息

ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);

先来了解一个接口:ScopeMetadataResolver,用于解析bean定义范围的策略接口。

public interface ScopeMetadataResolver {
        //解析bean定义范围,返回一个描述bean定义范围的对象ScopeMetadata
        ScopeMetadata resolveScopeMetadata(BeanDefinition definition);
    }

AnnotatedBeanDefinitionReader的scopeMetadataResolver是ScopeMetadataResolver的实现类AnnotationScopeMetadataResolver。

@Override
    public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
        ScopeMetadata metadata = new ScopeMetadata();
        if (definition instanceof AnnotatedBeanDefinition) {
            AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
            //获取注解类型是this.scopeAnnotationType类型的属性,
            //protected Class<? extends Annotation> scopeAnnotationType = Scope.class;
            AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
                    annDef.getMetadata(), this.scopeAnnotationType);
            if (attributes != null) {
                //获取scope的value值
                metadata.setScopeName(attributes.getString("value"));
                ......
            }
        }
        return metadata;
    }

03

给AnnotatedGenericBeanDefinition设置scope

abd.setScope(scopeMetadata.getScopeName());

04

获取beanName,如果registerBean没有指定name则根据bean名称产生器产生一个beanName

String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
  

bean名称产生器接口:BeanNameGenerator

public interface BeanNameGenerator {
        /**
         * 为给定的bean定义生成bean名称。
         * 参数1:BeanDefinition
         * 参数2:BeanDefinition注册器
        */
        String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry);
    }

这里使用的是它的实现类AnnotationBeanNameGenerator

@Override
    public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
        if (definition instanceof AnnotatedBeanDefinition) {
            //调用determineBeanNameFromAnnotation方法获取
            String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
            if (StringUtils.hasText(beanName)) {
                return beanName;
            }
        }
        return buildDefaultBeanName(definition, registry);
    }
protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
        //获取注解元数据,描述该bean的注解信息
        AnnotationMetadata amd = annotatedDef.getMetadata();
        //获取该bean的所有注解的类型
        Set<String> types = amd.getAnnotationTypes();
        String beanName = null;
        for (String type : types) {
            //获取注解类型上的属性
            AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
            //调用isStereotypeWithNameValue方法判断当前注解类型是否是@Component类型
            //或者被@Component注释的类:如@Service (org.springframework.stereotype包下的注解都是)
            //并且当前注解的属性中是否有名为“value”的属性。
            if (isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) {
                //获取注解的value属性的值,如果存储value属性的话
                Object value = attributes.get("value");
                if (value instanceof String) {
                    String strVal = (String) value;
                    if (StringUtils.hasLength(strVal)) {
                        if (beanName != null && !strVal.equals(beanName)) {
                            如果value的值与上一次循环获取的beanName不同抛出异常。
                            这是防止被@Service注解之后又使用@Component注解的情况
                        }
                        beanName = strVal;
                    }
                }
            }
        }
        return beanName;
    }

    protected boolean isStereotypeWithNameValue(String annotationType,
            Set<String> metaAnnotationTypes, Map<String, Object> attributes) {
                //如果注解类型annotationType是org.springframework.stereotype.Component
                //或者annotationType上有org.springframework.stereotype.Component注解,
                //比如:
                //@Component
                //public @interface Repository
                //即@Repository上被@Component注释
        boolean isStereotype = annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME) ||
                (metaAnnotationTypes != null && metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME)));
                //如果isStereotype条件成立且attributes不为空,且attributes中含有value属性,那么返回true。
                //attributes是annotationType注解的所有属性
        return (isStereotype && attributes != null && attributes.containsKey("value"));
    }

    如果前面注解都没有指定value,则调用buildDefaultBeanName方法把bean的类名作为bean的名称,首字母小写。
    protected String buildDefaultBeanName(BeanDefinition definition) {
        String shortClassName = ClassUtils.getShortName(definition.getBeanClassName());
        return Introspector.decapitalize(shortClassName);
    }

05

beanName获取到之后就是处理常用的定义注解

AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

AnnotationConfigUtils注解配置工具类的processCommonDefinitionAnnotations方法,

参数1是AnnotatedBeanDefinition,参数2是AnnotatedBeanDefinition的getMetadata()方法获取到的注解类型描述信息

static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
        //@Lazy注解
        if (metadata.isAnnotated(Lazy.class.getName())) {
            abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value"));
        }
        else if (abd.getMetadata() != metadata && abd.getMetadata().isAnnotated(Lazy.class.getName())) {
            abd.setLazyInit(attributesFor(abd.getMetadata(), Lazy.class).getBoolean("value"));
        }

        //@Primary注解
        if (metadata.isAnnotated(Primary.class.getName())) {
            abd.setPrimary(true);
        }
        //@DependsOn注解
        if (metadata.isAnnotated(DependsOn.class.getName())) {
            abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value"));
        }

        if (abd instanceof AbstractBeanDefinition) {
            AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
            //@Role注解
            if (metadata.isAnnotated(Role.class.getName())) {
                absBd.setRole(attributesFor(metadata, Role.class).getNumber("value").intValue());
            }
            //@Description注解
            if (metadata.isAnnotated(Description.class.getName())) {
                absBd.setDescription(attributesFor(metadata, Description.class).getString("value"));
            }
        }
    }

就只是将bean含有以上这些注解的信息读取到AnnotatedBeanDefinition中。

06

new一个BeanDefinition的持有者

BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

注册BeanDefinition到bean工厂,createBean的时候才能获取到这个bean的BeanDefinition

BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
public static void registerBeanDefinition(
            BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
            throws BeanDefinitionStoreException {

        // 在主beanName下注册bean定义。
        String beanName = definitionHolder.getBeanName();
        //调用的是DefaultListableBeanFactory的registerBeanDefinition方法
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

        // 注册bean名称的别名(如果有的话)。
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            for (String alias : aliases) {
                registry.registerAlias(beanName, alias);
            }
        }
    }

07

DefaultListableBeanFactory实现了BeanDefinitionRegistry接口。

//---------------------------------------------------------------------
    // Implementation of BeanDefinitionRegistry interface
    //---------------------------------------------------------------------

    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {

        BeanDefinition oldBeanDefinition;
        oldBeanDefinition = this.beanDefinitionMap.get(beanName);
        if (oldBeanDefinition != null) {
            ......
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }
        else {
            //hasBeanCreationStarted检查该工厂的bean创建阶段是否已经启动,即是否有任何bean已经标记为在此期间创建。
            if (hasBeanCreationStarted()) {
                synchronized (this.beanDefinitionMap) {
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    if (this.manualSingletonNames.contains(beanName)) {
                        Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
                        updatedSingletons.remove(beanName);
                        this.manualSingletonNames = updatedSingletons;
                    }
                }
            }
            else {
                //beanDefinitionMap保存的是所有bean的BeanDefinition
                this.beanDefinitionMap.put(beanName, beanDefinition);
                //beanDefinitionNames保存的是所有bean的名称,
                this.beanDefinitionNames.add(beanName);
                //单例bean的名称
                this.manualSingletonNames.remove(beanName);
            }
            this.frozenBeanDefinitionNames = null;
        }
        //如果旧的BeanDefinition不为空,且是单例的
        if (oldBeanDefinition != null || containsSingleton(beanName)) {
            //重置BeanDefinition,同时移除单例的bean
            resetBeanDefinition(beanName);
        }
    }

    DefaultListableBeanFactory的resetBeanDefinition方法
    protected void resetBeanDefinition(String beanName) {
        // 如果已经创建,则删除给定bean的合并bean定义。
        clearMergedBeanDefinition(beanName);

        // 销毁单例,让gc回收,具体过程就不深入了。
        destroySingleton(beanName);

        // 重置所有以给定bean为父bean的bean定义。
        for (String bdName : this.beanDefinitionNames) {
            if (!beanName.equals(bdName)) {
                BeanDefinition bd = this.beanDefinitionMap.get(bdName);
                if (beanName.equals(bd.getParentName())) {
                    resetBeanDefinition(bdName);
                }
            }
        }
    }

scan包扫描

这里还要补充一个bean的注册流程,就是从包扫描出发的。

01

AnnotationConfigApplicationContext类的另一个构造方法

public AnnotationConfigApplicationContext(String... basePackages) {
        this();
        scan(basePackages);
        refresh();
    }

scan方法

public void scan(String... basePackages) {
        this.scanner.scan(basePackages);
    }

ClassPathBeanDefinitionScanner的scan方法

public int scan(String... basePackages) {
        int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

        doScan(basePackages);
        if (this.includeAnnotationConfig) {
            AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
        }
        return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
    }

最后调用doScan方法完成扫描并注册bean。这个方法在第一篇介绍ClassPathBeanDefinitionScanner的时候提到过。

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
        for (String basePackage : basePackages) {
            //扫描每个basePackages下的bean,findCandidateComponents方法是具体的实现。
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
            for (BeanDefinition candidate : candidates) {
                // 遍历每个BeanDefinition,处理其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) {
                    // 处理常用定义注解,前面介绍过了
                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
                }
                if (checkCandidate(beanName, candidate)) {
                    //registerBeanDefinition 注册BeanDefinition,(注册bean)
                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                    definitionHolder =
                            AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                    beanDefinitions.add(definitionHolder);
                    registerBeanDefinition(definitionHolder, this.registry);
                }
            }
        }
        return beanDefinitions;
    }
#后端

声明:公众号、CSDN、掘金的曾用名:“Java艺术”,因此您可能看到一些早期的文章的图片有“Java艺术”的水印。

文章推荐

Spring源码分析(四)bean工厂初始化阶段

继续介绍AnnotationConfigApplicationContext工作流程,本篇介绍refresh方法,即bean工厂的初始化阶段。读完本篇你会了解到bean是什么时候被全部扫描成BeanDefinition注入到工厂中的。还有一些后置处理器的职责。

Spring源码分析(二)bean的创建过程

上一篇有说到过BeanDefinition,主要关注的是其扩展接口AnnotateBeanDefinition和其子类AnnotateGenericBeanDefinition。本篇先超前介绍spring是如果通过BeanDefinition来创建一个bean的。

Spring源码分析(一)理解一些类及接口

本篇主要介绍一些重要的接口及类,下一篇介绍bean的创建过程,接着介绍AnnotationConfigApplicationContext的初始化流程,最后一篇通过源码总结bean的生命周期。

Java的class文件结构解读

相信你也很好奇.java文件编译后的.class文件结构?我也很好奇,所以来了就一起挖一挖这个坑吧。这是我读《深入理解java虚拟机》这本书的第六章“类文件结构”之后写的,目的是为了帮助大家更好的理解这一章的内容。

你是否还看不懂UML图?

你有没有发现你阅读的技术文档都能看到uml图,所以最起码的用例图、类图和时序图得要能看得懂,不然这将是你进阶路上的拦路虎。

在下面的数中间填上“+”,“-”,使计算结果为100:123456789=100

在下面的数中间填上“+”,“-”,使计算结果为100:123456789=100。