暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

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

Java艺术 2021-09-09
600
欢迎将文章分享到朋友圈
如需转载,请在后台回复“转载”获取授权


转载是一种动力 分享是一种美德


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

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


spring版本:4.3.18


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


>>>>

BeanDefinition


了解BeanDefinition是什么:

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

public interface BeanDefinition extends AttributeAccessorBeanMetadataElement {

    //单例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配置文件的时候,并不是将每一个<bean>直接解析生产一个实例,而是统一的将所有的<bean>都解析为一个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的功能: 

  • MessageSource:为应用提供国际化访问功能 

  • ResourceLoader:提供资源(如URL和文件系统)的访问支持 

  • ApplicationEventPublisher:引入事件机制,包括启动事件、关闭事件等,让容器在上下文中提供了对应用事件的支持。


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


重点关注的三个ApplicationContext:

  • FileSystemXmlApplicationContext:根据文件路径加载xml配置文件启动ApplicationContext。

  • ClassPathXmlApplicationContext:根据类路径加载xml文件启动ApplicationContext。

  • AnnotationConfigApplicationContext:初始化一个支持注解的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> 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> getBean(Class<T> requiredType) throws BeansException;


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

复制





文章转载自Java艺术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论