注:全文中的英文注释来源源码,因为自己翻译不靠谱,所以给出原文
对于Java来说还有很多需要学习的,初识源码还有很多错误,忘指正!!!
第一天总结也就是下面这个图,Bean生命周期流程图:
一种框架,一种生态。在这个生态下诞生了很多产品,boot,cloud等等,因此具有很强的扩展性。
IOC 控制反转,这是一种思想,将创建对象的过程交给spring容器统一管理。在spring的具体实现是DI(依赖注入); AOP 面向切面编程, 基于动态代理
xml配置文件, 注解;在扫描配置信息后会生成BeanDefinition对象,存储了bean的具体信息。
我们实际操作过程中会使用getBean获取容器对象,而采用的方式可以分为byName, byType;可以看出两种类型:String和Class
根据我们获取对象的方式,可以得出结论:使用Map集合作为存储; key:String/Class/..
value:bean对象/Object/... 其他的可以另行猜测,开始的时候就猜猜看呗
最常听见的答案:反射
上面几个问题大致描述了下使用spring的流程:xml文件 -》 对象信息 -》 实例化 -》对象存储 -》 使用; 如图:
这里解析应该针对不同的文件,例如我们使用的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()实例化;但是中间也需要很多额外的操作用于增强
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等方法,进行获取
后置处理器/增强器,提供了动态操作BeanDefinition信息的能力。
为什么要修改?装逼?,实际上我们常使用的数据库配置,常使用占位符,如 ${driver.url},现在可以想想他怎么解析的?
Spring中顶级有两个增强器:
我们使用的资源解析增强器:
/**
* spring提供的一个工具类,用于解析bean定义中属性值里面的占位符,此类不能被直接实例化使用
*
* Abstract base class for property resource configurers that resolve placeholders
* in bean definition property values.
* 例子:
*
*
*
*/
BeanFactory结束后,可以进行对象的创建过程。整个流程又分为实例化和初始化,即:
紧接着,会到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;
}
}
增强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的生命周期:
两者都是用来创建对象的,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的工厂,在实现接口后,他就具有了暴露
第一天没总结完。。。太晚了,明天补
给自己加加油!!!
第一天总结:主要得到整个spring加载的大致流程,其中内部的细节还没有深究;其中涉及了一些重要的接口:BeanFactory, BeanDefinition, BeanDefinitionReader, BeanPostProcessor, BeanFactoryPostProcessor, Aware等等;可以先了解这些接口的大致作用;
对于整个加载流程可以从:解析文件 -》 加载对象 -》 使用对象 -》 销毁对象,逐步细化