【spring源码第一天】概述流程

【spring源码第一天】概述流程,第1张

注:全文中的英文注释来源源码,因为自己翻译不靠谱,所以给出原文

对于Java来说还有很多需要学习的,初识源码还有很多错误,忘指正!!!

第一天总结也就是下面这个图,Bean生命周期流程图:

1. 思考 1.1 什么是spirng?

一种框架,一种生态。在这个生态下诞生了很多产品,boot,cloud等等,因此具有很强的扩展性。

1.2 spring的核心?

IOC 控制反转,这是一种思想,将创建对象的过程交给spring容器统一管理。在spring的具体实现是DI(依赖注入); AOP 面向切面编程, 基于动态代理

1.3 怎么将对象交付给容器的?

xml配置文件, 注解;在扫描配置信息后会生成BeanDefinition对象,存储了bean的具体信息。

1.4 spring怎么存储对象?

我们实际 *** 作过程中会使用getBean获取容器对象,而采用的方式可以分为byName, byType;可以看出两种类型:String和Class

根据我们获取对象的方式,可以得出结论:使用Map集合作为存储; key:String/Class/..

value:bean对象/Object/... 其他的可以另行猜测,开始的时候就猜猜看呗

1.5 怎么实例化对象?

最常听见的答案:反射

2 概述

上面几个问题大致描述了下使用spring的流程:xml文件 -》 对象信息 -》 实例化 -》对象存储 -》 使用; 如图:

2.1 解析

        这里解析应该针对不同的文件,例如我们使用的xml, boot中的properties, yaml等,甚至我们使用注解,都需要解析的 *** 作,去让spring知道我们怎么创建bean对象,然后生成BeanDefinition来进行存储。

        而spring拥有强大的扩展性,如果我们以后需要其他配置文件类型怎么办? 因此我们需要一套规范(Interface),然后由具体实现类去完成

/* BeanDefinitionReader:
 * 定义资源文件读取并转换为BeanDefinition的各个功能
 *
 * Simple interface for bean definition readers.
 * Specifies load methods with Resource and String location parameters.
*/

        流程来说应该是实例化,实例化说了通过反射将BeanDefinition对象进行解析,然后newInstance()实例化;但是中间也需要很多额外的 *** 作用于增强

2.2 BeanFactory

        BeanFactory是spring中重要的工厂,用于获取基础的spring容器,进而获取bean对象

/**
 * BeanFactory
 * 定义获取bean及bean的各种属性
 * The root interface for accessing a Spring bean container.
 * 
 * beanFactory中有beanDefinition信息
 * This interface is implemented by objects that hold a number of bean definitions
*/

看注释,bean definitions在factory中,因此可以了解在实例化前一定会从factory中进行反射

BeanFactory还有很多实现,比如AbstractApplicationContext中提供了getBeanDefinitionNames等方法,进行获取

2.3 PostProcessor

后置处理器/增强器,提供了动态 *** 作BeanDefinition信息的能力。

为什么要修改?装逼?,实际上我们常使用的数据库配置,常使用占位符,如 ${driver.url},现在可以想想他怎么解析的?

Spring中顶级有两个增强器:

 

 我们使用的资源解析增强器:

/**
 * spring提供的一个工具类,用于解析bean定义中属性值里面的占位符,此类不能被直接实例化使用
 *
 * Abstract base class for property resource configurers that resolve placeholders
 * in bean definition property values. 
 * 例子:
 * 
 *   
 * 
*/

BeanFactory结束后,可以进行对象的创建过程。整个流程又分为实例化和初始化,即:

2.4 Aware接口 

紧接着,会到Aware接口;这个接口会通过回调方法获取到spring容器中的对象

/**
 * A marker superinterface indicating that a bean is eligible to be notified by the
 * Spring container of a particular framework object through a callback-style method.   
*
public interface Aware {

}

在Aware下有很多是实现的接口,可以通过实现获取不同的spring容器对象:

自定义样例,将获取的容器对象作为自己的一个成员变量就行赋值和调用:

public class B implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public void show() {
        System.out.println("获取applicationContext对象----");
        A bean = applicationContext.getBean(A.class);
        System.out.println(bean);
        System.out.println("获取applicationContext对象 end----");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
2.5 BeanPostProcessor

增强Bean信息的后置处理器,相比于BeanFactory增强器,提供了bean初始方法init-method前后两种增强方式:

public interface BeanPostProcessor {
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
}

常见的场景是实现aop,用于动态代理,可以找一个接口:

查看流程:

protected Object createProxy(Class beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource)

进入最后:return proxyFactory.getProxy(getProxyClassLoader());  // getProxy方法

继续:
public Object getProxy(@Nullable ClassLoader classLoader) {
	// createAopProxy() 用来创建我们的代理工厂
	return createAopProxy().getProxy(classLoader);
}

最后进行 AopProxy接口,其实现类有JDK和CGlib两种

 综上,我们可以得出后续流程,也就是整个bean的生命周期:

 

 2.6 FactoryBean和BeanFactory的区别?

两者都是用来创建对象的,BeanFactory是spring容器的入口,对象的创建遵循完整的生命周期,有spring进行管理。

而FactoryBean由自定义实现,通过调用getObject得到具体对象,整个过程自己可以控制;

/**
 * If a bean implements this
 * interface, it is used as a factory for an object to expose, not directly as a
 * bean instance that will be exposed itself.
 *
 * but the object exposed for bean
 * references ({@link #getObject()}) is always the object that it creates.
*/

从源码注释中:实现FactoryBean接口的对象会被作为一种暴露工厂,提供暴露对象的能力,使用getObject总是得到他所创建的对象

自定义样例:

public class CFactoryBean implements FactoryBean {

    @Override
    public A getObject() throws Exception {
        return new A();
    }

    @Override
    public Class getObjectType() {
        return null;
    }
}

@Test
public void Test08() {
	String config = "applicationContext.xml";
	ApplicationContext ac = new ClassPathXmlApplicationContext(config);
	A a = (A) ac.getBean("cFactoryBean");
	System.out.println(a);
}

         这里实现类一个CFactoryBean的工厂,在实现接口后,他就具有了暴露执行泛型对象的能力;在我们getBean()这个工厂的时候,他默认调用getObject()方法,最终得到了A对象

总结

第一天没总结完。。。太晚了,明天补

给自己加加油!!!

第一天总结:主要得到整个spring加载的大致流程,其中内部的细节还没有深究;其中涉及了一些重要的接口:BeanFactory, BeanDefinition, BeanDefinitionReader, BeanPostProcessor, BeanFactoryPostProcessor, Aware等等;可以先了解这些接口的大致作用;

对于整个加载流程可以从:解析文件 -》 加载对象 -》 使用对象 -》 销毁对象,逐步细化

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/795163.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-06
下一篇 2022-05-06

发表评论

登录后才能评论

评论列表(0条)

保存