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

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

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

本文链接:https://wujiuye.com/article/7e4d43ab25a74b27a33683781126341e

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

一直在摸索spring框架,看了《Spring技术内幕》和《Spring源码深度解析》,而这两本书在讲Spring IOC容器的时候都是讲xml配置方式的,但我觉得基于注解的方式没有读取解析xml文件会更简单。

spring版本:4.3.18

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

BeanDefinition

了解BeanDefinition是什么:

这是一个接口,从接口名称可以看出这是对bean定义的抽象。

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

    //单例singleton
    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
    //原型prototype
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

    //写入bean的类型
    void setBeanClassName(String beanClassName);
    //获取bean的类型
    String getBeanClassName();

    //写入scope(范围)即是否单例
    void setScope(String scope);
    //获取Scope
    String getScope();

    //设置是否懒初始化
    void setLazyInit(boolean lazyInit);
    //是否懒初始化(getBean的时候再初始化)
    boolean isLazyInit();

    //获取构造参数值
    ConstructorArgumentValues getConstructorArgumentValues();

    //获取属性值
    MutablePropertyValues getPropertyValues();

    //是否单例
    boolean isSingleton();

    //是否原型
    boolean isPrototype();

    //返回原始的BeanDefinition
    BeanDefinition getOriginatingBeanDefinition();
    /**
     * 设置此bean初始化所依赖的bean的名称。
     * bean工厂将确保这些bean首先被初始化。
     */
    void setDependsOn(String... dependsOn);

    /**
     * 返回此bean所依赖的bean名称。
     */
    String[] getDependsOn();

这是被我简化过的BeanDefinition源码。

图片

spring在读取xml配置文件的时候,并不是将每一个直接解析生产一个实例,而是统一的将所有的都解析为一个BeanDefinition对象,最后不管是不是单例的getBean获取一个bean的时候都是通过BeanDefinition对象生成的对象。如果是单例的且非懒初始化那么bean在容器初始化的时候就被初始化存放到bean容器了,如果是单例且懒初始化那么会在用到的时候才会实例化且存入到bean容器中。基于注册也是一样的,被@Component等注解声明的类都会被解析为BeanDefinition存放在bean工厂,最后才根据BeanDefinition生成目标对象。

图片

因为我要说的是基于注解方式的bean容器初始化过程,所以我只关注AnnotateGenericBeanDefinition,该类继承GenericBeanDefinition且实现了AnnotateBeanDefinition接口,GenericBeanDefinition是一个通过的BeanDefinition,AnnotateGenericBeanDefinition就只是多实现了一个AnnotateBeanDefinition接口。

public interface AnnotatedBeanDefinition extends BeanDefinition {

    //获取这个beandefinition描述的类的注解元数据(描述注解的数据),理解为获取注解信息就好了。
    AnnotationMetadata getMetadata();

    //获取工厂方法信息
    MethodMetadata getFactoryMethodMetadata();

}

ApplicationContext

ApplicationContext理解为应用上下文,实现了BeanFactory接口,是bean的管理者。ApplicationContext扩展了很多使用的功能,如Bean的生命周期管理、框架事件体系、国际化支持等。同时,ApplicationContext接口还通过继承其他接口扩展了BeanFactory的功能:

常用的ApplicationContext都是继承AbstractApplicationContext(不是直接继承就是父类或父类的父类继承了)。

图片

重点关注的三个ApplicationContext:

AnnotationConfigApplicationContext的一个直接子类是GenericApplicationContext,所有继承自GenericApplicationContext的应用上下文都是通过内部持有一个DefaultListableBeanFactory实例实现工厂功能的,虽然ApplicationContext实现了BeanFactory接口。

AnnotationConfigApplicationContext实现了AnnotationConfigRegistry接口。可以将bean(被@Component等声明的类)直接注册到AnnotationConfigApplicationContext中,或者注册@Configuration声明的配置类,在配置类中以声明包扫描的方式或者使用@Bean来向容易中注入bean。

//注解配置应用程序上下文的通用接口
public interface AnnotationConfigRegistry {

    //注册一个或多个要处理的带注释的类。
    void register(Class<?>... annotatedClasses);

    //扫描指定的一个或多个包
    void scan(String... basePackages);
}

BeanFactory

public interface BeanFactory {

    //注册实现FactoryBean接口的bean,如果想要获取FactoryBean本身则在bean名称前面添加“&”字符。
    String FACTORY_BEAN_PREFIX = "&";


    //返回指定bean的一个实例,bean不存在则创建
    Object getBean(String name) throws BeansException;

    /**
     * 返回一个bean的实例,bean不存在则创建
     * @param name bean的名称(id)
     * @param requiredType 可以是bean实现的接口或者继承的父类
     */
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;


    Object getBean(String name, Object... args) throws BeansException;

    /**
     * 支持泛型方式获取bean,这样获取到bean的时候就不需要强制类型转换了
     * 如果没有找到给定类型的bean,则抛出NoSuchBeanDefinitionException
     * 如果无法创建bean,则抛出BeansException
     * 如果指定的类型有多个bean则会抛出NoUniqueBeanDefinitionException异常
     */
    <T> T getBean(Class<T> requiredType) throws BeansException;


    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;


    /**
     * 是否存在具有给定名称的bean
     */
    boolean containsBean(String name);

    /**
     * 指定的bean是否是单例的
     */
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    /**
     * 指定的bean是否是原型
     */
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    /**
     * 检查具有给定名称的bean是否与指定的类型匹配。
     */
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

    /**
     * 确定具有给定名称的bean的类型。
     */
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;

    /**
     * 获取bean的所有别名,如果不存在别名则返回空
     */
    String[] getAliases(String name);

}

接着看一个BeanFactory接口的扩展接口ListableBeanFactory,前面说过AbstractApplicationContext是通过内部持有一个DefaultListableBeanFactory对象作为真正的bean工厂的,而AnnotationConfigApplicationContext也是AbstractApplicationContext的子类,这些后面再说。DefaultListableBeanFactory实现ConfigurableListableBeanFactory接口,ConfigurableListableBeanFactory接口又是ListableBeanFactory的扩展接口。

ListableBeanFactory接口源码,去掉了一些方法的定义。

public interface ListableBeanFactory extends BeanFactory {

    /**
     * 检查此bean工厂是否包含具有给定名称的BeanDefinition。
     * 忽略通过BeanDefinition以外的其他方式注册的任何单例bean,
     * 如:@Bean定义的
     */
    boolean containsBeanDefinition(String beanName);

    /**
     * 获取BeanDefinition的总数
     */
    int getBeanDefinitionCount();

    /**
     * 获取所有的BeanDefinition的名称
     */
    String[] getBeanDefinitionNames();

     ......

    String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);


    <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
    <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
            throws BeansException;

    /**
     * 获取所有被指定类型注解注释的bean的名称
     */
    String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);

    /**
     * 获取所有被指定类型的注解注释的bean
     */
    Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;

    /**
     * 在bean中查找指定类型的注解
     * @param beanName 要查找的注解的bean的名称
     * @param annotationType 注解类型
     */
    <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
            throws NoSuchBeanDefinitionException;

}

BeanFactoryPostProcessor

BeanFactory后置处理器,实现该接口的类,在@Configuration注解的配置类上添加

@Import({BeanFactoryPostProcessor实现类.class})

可将该类注册为一个bean,在bean工厂准备好之后(单例的bean还没有被实例化)调用,主要是用来自定义修改持有的bean的定义信息。

public interface BeanFactoryPostProcessor {

    /**
     * 在应用程序上下文的标准初始化之后修改其内部bean工厂。
     * 所有bean定义都已经加载,但是还没有实例化bean。
     * 这允许覆盖或添加属性,甚至可以初始化bean。
     * @param beanFactory 应用程序上下文使用的bean工厂
     * 
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

ConfigurableListableBeanFactory是ListableBeanFactory接口的扩展,DefaultListableBeanFactory实现了该ConfigurableListableBeanFactory接口,而AnnotationConfigApplicationContext应用上下文使用的bean工厂是DefaultListableBeanFactory实例。所以这里的参数实际上就是DefaultListableBeanFactory实例。

//AnnotationConfigApplicationContext
public class AnnotationConfigApplicationContext 
extends GenericApplicationContext 
implements AnnotationConfigRegistry {
}

//GenericApplicationContext
public class GenericApplicationContext 
extends AbstractApplicationContext 
implements BeanDefinitionRegistry {

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

BeanFactoryPostProcessor的使用:

自定义MyBeanFactoryPostProcessor实现BeanFactoryPostProcessor接口。

public class MyBeanFactoryPostProcessor 
implements BeanFactoryPostProcessor {
    @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());
        }
    }
}

在postProcessBeanFactory方法打印bean工厂中所有BeanDefinition的属性值信息(key=字段名,value=将要注入的值)。当然现在还不起作用,需要在被添加

@Import({MyBeanFactoryPostProcessor.class})

这样才会起作用。还有另一种,在new AnnotationConfigApplicationContext的时候给AnnotationConfigApplicationContext注册的配置类中的包扫描添加一个扫描MyBeanFactoryPostProcessor所在包的@ComponentScan注解。

@ComponentScans中添加一个
@ComponentScan("wjy.stu.dao")

在MyBeanFactoryPostProcessor类上添加@Configuration。最后还有一种就是可以直接在配置类中使用@Bean注册一个MyBeanFactoryPostProcessor的实例。

BeanPostProcessor

bean的后置处理器。前面BeanFactoryPostProcessor是BeanFactory的后置处理器,在bean工厂准备就绪单例bean还没有被初始化的时候被调用。bean的后置处理器则是在bean初始化前后被调用。注意,是容器中所有的bean在调用初始化方法前后都会调用这个BeanPostProcessor的postProcessBeforeInitialization方法和postProcessAfterInitialization方法。不管是单例的还是原型的,都会被应用到,如果不是单例的那么每次调用getBean都会根据BeanDefinition创建一个bean实例,在创建bean的过程中仍然会调用bean的初始化方法,所以也会调用BeanPostProcessor的方法。

public interface BeanPostProcessor {

    /**
     * 将这个BeanPostProcessor应用到给定的新bean实例 ,在bean调用初始化方法之前被调用。
     * @param bean 新的bean实例
     * @param beanName 这个bean的名称
     * @return 返回参数传递过来的原始bean,或者在该方法中修改过之后的bean;
     */
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    /**
     * 将这个BeanPostProcessor应用到给定的新bean实例 ,在bean调用初始化方法完成之后被调用。
     * @param bean 新的bean实例
     * @param beanName 这个bean的名称
     * @return 返回参数传递过来的原始bean,或者在该方法中修改过之后的bean;
     */
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

在bean初始化时调用初始化方法之前和调用初始化方法之后分别调用applyBeanPostProcessorsBeforeInitialization方法和applyBeanPostProcessorsAfterInitialization方法。

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        ......
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }catch (Throwable ex) {
            ......
        }
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }

在这里提一下这个invokeInitMethods方法。

如果bean实现了InitializingBean接口,则会先调用该bean的afterPropertiesSet方法。

@Component
public class ScoreBean implements InitializingBean {


    @Override
    public void afterPropertiesSet() throws Exception {

    }
}

如果该bean的BeanDefinition存在initMethod方法,比如@Bean注解声明的初始化方法:@Bean(initMethod = “init”)

当该bean没有实现InitializingBean接口的时候才会被调用,避免了调用多个初始化方法的情况。

protected void invokeInitMethods(String beanName, 
final Object bean, RootBeanDefinition mbd)
            throws Throwable {

        boolean isInitializingBean = (bean instanceof InitializingBean);
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
            if (System.getSecurityManager() != null) {
                try {
                    AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        @Override
                        public Object run() throws Exception {
                            ((InitializingBean) bean).afterPropertiesSet();
                            return null;
                        }
                    }, getAccessControlContext());
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                ((InitializingBean) bean).afterPropertiesSet();
            }
        }

        if (mbd != null) {
            String initMethodName = mbd.getInitMethodName();
            if (initMethodName != null && !(isInitializingBean 
                && "afterPropertiesSet".equals(initMethodName)) 
                && !mbd.isExternallyManagedInitMethod(initMethodName)) {
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }

AnnotatedBeanDefinitionReader

负责将被注解声明的bean读取为一个BeanDefinition。这是ClassPathBeanDefinitionScanner的替代方法,它应用相同的注解解析,但仅适用于显式注册的类。显示注册就是直接调用AnnotationConfigApplicationContext的register方法注册的类,或者AnnotationConfigApplicationContext构造方法中传入的类。

同ClassPathBeanDefinitionScanner都是在AnnotationConfigApplicationContext的构造方法中被实例化。

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

调用AnnotationConfigApplicationContext的register方法实际上调用的是AnnotatedBeanDefinitionReader的register方法。

public void register(Class<?>... annotatedClasses) {
        Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
        this.reader.register(annotatedClasses);
    }

在registerBean方法中通过要注册的类构造一个AnnotatedGenericBeanDefinition对象,这实际上是一个StandardAnnotationMetadata对象,后面再详细说名。通过ScopeMetadataResolver解析注册的类的Scope。给该BeanDefinition设置Scope。AnnotationConfigUtils.processCommonDefinitionAnnotations方法处理常用的定义注解。

public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            return;
        }

        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        abd.setScope(scopeMetadata.getScopeName());
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        if (qualifiers != null) {
            for (Class<? extends Annotation> qualifier : qualifiers) {
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                }
                else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                }
                else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }

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

BeanDefinitionHolder:

BeanDefinitionHolder是BeanDefinition的持有者。

public class BeanDefinitionHolder implements BeanMetadataElement {

    private final BeanDefinition beanDefinition;

    private final String beanName;

    private final String[] aliases;

    public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName) {
        this(beanDefinition, beanName, null);
    }


    public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName, String[] aliases) {
        this.beanDefinition = beanDefinition;
        this.beanName = beanName;
        this.aliases = aliases;
    }


    public BeanDefinitionHolder(BeanDefinitionHolder beanDefinitionHolder) {
        this.beanDefinition = beanDefinitionHolder.getBeanDefinition();
        this.beanName = beanDefinitionHolder.getBeanName();
        this.aliases = beanDefinitionHolder.getAliases();
    }


    /**
     * 返回BeanDefinition.
     */
    public BeanDefinition getBeanDefinition() {
        return this.beanDefinition;
    }

    /**
     * 返回BeanDefinition的beanName
     */
    public String getBeanName() {
        return this.beanName;
    }

    /**
     * 返回BeanDefinition的别名
     */
    public String[] getAliases() {
        return this.aliases;
    }

    @Override
    public Object getSource() {
        return this.beanDefinition.getSource();
    }


    public boolean matchesName(String candidateName) {
        return (candidateName != null && (candidateName.equals(this.beanName) ||
                candidateName.equals(BeanFactoryUtils.transformedBeanName(this.beanName)) ||
                ObjectUtils.containsElement(this.aliases, candidateName)));
    }
}

最后调用BeanDefinitionReaderUtils的registerBeanDefinition方法将BeanDefinition注册到bean工厂中。

ClassPathBeanDefinitionScanner

扫描指定包下的所有被spring注解注解过的类(如@Component),并生成对应的BeanDefinition。

在AnnotatedBeanDefinitionReader的scan方法中调用ClassPathBeanDefinitionScanner的scan方法,返回值是扫描这些包注册的bean的总数。

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

最终调用ClassPathBeanDefinitionScanner的doScan方法。

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        //保存扫描结果BeanDefinitionHolder是BeanDefinition的持有者
        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
        //所有包逐个扫描
        for (String basePackage : basePackages) {
            //获取一个包下的所有BeanDefinition
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
            for (BeanDefinition candidate : candidates) {
                //一个个设置Scope
                ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
                candidate.setScope(scopeMetadata.getScopeName());
                //获取bean的名称,如果不指定beanName默认使用类名且首字母小写
                String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                if (candidate instanceof AbstractBeanDefinition) {
                    postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
                }
                //如果这个BeanDefinition实现了AnnotatedBeanDefinition接口,由于我们讨论的是AnnotationConfigApplicationContext,所以这里会是true。
                if (candidate instanceof AnnotatedBeanDefinition) {
                    //处理常用定义注解
                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
                }
                if (checkCandidate(beanName, candidate)) {
                    //这里跟AnnotatedBeanDefinitionReader的registerBean方法一样,生成BeanDefinitionHolder,将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源码分析ioc容器总结篇

这篇文章是对前面几篇文章做一个小节,本篇不写一行代码,单纯的文字总结。

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

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

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

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

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

介绍AnnotationConfigApplicationContext工作流程,本篇先介绍registerBean方法内部执行流程分析。

Java的class文件结构解读

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

你是否还看不懂UML图?

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