miniSpring阅读

124 阅读7分钟

mini-spring阅读

IOC

image.png

bean容器实现了BeanDefinitionRegistry接口和SingletonBeanRegistry接口,先向容器中注册BeanDefinition,等到bean需要使用的时候进行实例化。

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
		BeanDefinition beanDefinition = new BeanDefinition(HelloService.class);
		beanFactory.registerBeanDefinition("helloService", beanDefinition);//存入beanDefinitionMap

		HelloService helloService = (HelloService) beanFactory.getBean("helloService"); 

DefaultListableBeanFactory

1、  BeanDefinition的存储 beanName - beanDefinition

ConcurrentHashMap存储BeanDefinition (registerBeanDefinition、getBeanDefinition、containsBeanDefinition)

2、  实例化Bean

getBean() 在DefaultSingletonBeanRegistry里从三级缓存中检查是否以及有实例。

在AbstractBeanFactory里进行以下判断

1、  如果三级缓存中有实例且是FactoryBean。如果是单例,直接从factorybean缓存中取,如果没有则生成一个factorybean放入factorybean的缓存。如果是prototype,创建新的factorybean。

2、  如果三级缓存里没有实例,根据beanName获取beanDefinition,执行createBean()方法,返回实例化后的对象。

单例第一次创建,在doCreateBean()里会创建一个对象工厂,并将工厂放到三级缓存里(解决循环依赖)。

3、根据类型返回所有的bean实例

如果传入的类是beanDefinitionMap里类的实现类,则返回。

bean属性填充

1、  属性为普通类型

a)  在beanDefinition的propertyValues中定义不同类型的属性和值。

b)  将beanDefinition注册到beanDefinitionMap中。

c)  当getBean()后,首先检查三级缓存中是否有实例。没有实例,则通过beanDefinition先创建一个bean实例。

d)  在doCreateBean()中根据bean实例化策略(构造器创建、cglib创建)返回新建的空bean。

e)  如果beanDefinition是单例,则创建一个单例的bean工厂存入三级缓存提前暴露。

f)  xxxxbeanPostProcessor

g)  applyPropertyValues(),循环beanDefinition的propertyValues,取出值并进行类型转换,通过反射设置属性。

h)  xxxxbeanPostProcessor前置、afterPropertiesSet、后置处理

2、  属性为对象

Person里赋值Car类型

在设置属性的时候,判断出对象是BeanReference类型的实例,则调用getBean(),获取一个新的car实例。第一次三级缓存中没有car,则自动创建一个car工厂存入三级缓存,并对car进行初始化。

car初始化完成,如果是单例bean,会自动存入一级缓存,并删除二级和三级缓存的实例。

最后用反射将car填入person。

xml定义bean

传入xml的路径location。doLoadBeannDefinitions()解析是否有"component-scan"标签。根据标签取出所有的bean的list,遍历每个bean取出id、beanName、className等等信息放到beanDefinition里。如果bean中带有RefAttribute,新建一个BeanReference类作为value存入beanDefinition。

BeanFactoryPostProcessor(Bean工厂后置处理器)

BeanFactoryPostProcessor是spring提供的容器扩展机制,在BeanDefinitionMap填充完毕,Bean实例化之前执行。允许在bean实例化之前修改BeanDefinition的信息。

● 实现类1:PropertyPlaceholderConfigurer用properties文件配置值替换xml文件里的占位符。

● 实现类2:CustomEditorConfigurer实现类型转换。

BeanPostProcessor(Bean后置处理器)

在Spring容器创建过程中,初始化bean前后回调BeanPostProcessor定义的方法。

1.  postProcessBeforeInitialization()在bean对象初始化方法之前回调

2.  postProcessAfterInitialization()在bean对象初始化方法之后回调

● beanDefinition注册完成后,执行getBean()方法。从三级缓存中检查是否已经有单例,没有则执行createBean()的doCreateBean()。

● 实例化对象后,经过一系列步骤,进入initializeBean()方法。

● initializeBean()中会依次执行applyBeanPostProcessorsBeforeInitialization()前置处理、invokeInitMethods()初始化、applyBeanPostProcessorsAfterInitialization()后置处理。

● applyBeanPostProcessorsBeforeInitialization()、applyBeanPostProcessorsAfterInitialization()中传入bean对象和beanName参数遍历List执行前置或者后置处理的方法。最后返回bean对象。

	protected Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) {
		if (bean instanceof BeanFactoryAware) {
			((BeanFactoryAware) bean).setBeanFactory(this);
		}

		//执行BeanPostProcessor的前置处理
		Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);

		try {
			invokeInitMethods(beanName, wrappedBean, beanDefinition);
		} catch (Throwable ex) {
			throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", ex);
		}

		//执行BeanPostProcessor的后置处理
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		return wrappedBean;
	}

ApplicationContext(区别于BeanFactory)

ApplicationContext相比于BeanFactory是一种更加先进的IOC容器。BeanFactory中的beanPostProcessor前后置处理需要手动添加,ApplicationConetxt可以自动识别。此外还有资源加载、容器事件监听、bean单例自动初始化等等。

重点是AbstractApplicationContext的refresh()方法。

1.  传入beanDefinition的xml文件的classPath,存入configLocations中。执行refresh()。

2.  refreshBeanFactory():先创建一个beanFactory,通过遍历configLocations,读取所有的xml中bean信息,并注册到beanDefinitionMap。(普通bean对象、beanFactoryPostProcessor、beanPostProcessor等)

3.  添加ApplicationContextAwareProcessor(还没看)

4.  执行BeanFactoryPostProcessor

5.  执行registerBeanPostProcessor方法的注册(在bean实例化之前注册)

6.  初始化事件发布者(还没看)

7.  注册事件监听器(还没看)

8.  注册类型转换器(还没看)以及初始化单例bean。初始化bean时,遍历beanDefinitionMap,如果是单例且不是懒加载,则getBean()。

9.  发布容器刷新完成事件。

image.png

图:bean目前为止的生命周期

bean初始化和销毁(实现接口先执行、自定义方法后执行)

● 在xml文件中制定init-method和destroy-method

● 继承自InitializingBean和DisposableBean

● 在方法上加注解PostConstruct和PreDestroy

初始化方法在bean填充属性完成之后进行:

//在设置bean属性之前,允许BeanPostProcessor修改属性值
applyBeanPostProcessorsBeforeApplyingPropertyValues(beanName, bean, beanDefinition);
//为bean填充属性
applyPropertyValues(beanName, bean, beanDefinition);
//执行bean的初始化方法和BeanPostProcessor的前置和后置处理方法
bean = initializeBean(beanName, bean, beanDefinition);

bean初始化方法为invokeInitMethods()。

1.  判断bean是否实现了InitializingBean接口。执行afterPropertiesSet()方法。

2.  获取initMethodName,通过反射执行bean的初始化方法。

当bean初始化完成后,会向容器注册销毁方法。

在registerDisposableBeanIfNecessary()中,判断bean为单例,且实现了DisposibleBean接口或者自定义了destroyMethodName的方法,将该bean进行销毁注册。

注册的bean为DisposableBeanAdapter类型。destroy()方法里,如果判断出实现了DisposibleBean接口,会先执行destroy。接着如果自定义销毁方法,则用反射执行自定义的销毁方法。

image.png 图:加入初始化和销毁的bean生命周期

Aware接口

常用的Aware接口为BeanFactoryAware和ApplicationContextAware,能够让bean感知所属的beanFactory和ApplicationContext。

BeanFactoryAware在初始化bean的时候设置了beanFactoryy。

ApplicationContextAware在bean的beanPostProcessor前置处理中设置所属的ApplicationContext。

bean的prototype作用域

bean的scope为prototype时,bean实例化后不会添加进singletonObjects一级缓存。销毁的时候也不会执行destroy方法(只有singleton会注册销毁方法)。

image.png

FactoryBean

FactoryBean是一个接口,用于创建和管理bean对象。核心方法有getObject()用于创建对象实例(自定义创建逻辑)、isSingleton()。

在ApplicationContext的refresh()中会提前实例化单例bean:getBean()方法首先会生成该bean的单例对象,当检测到是FactoryBean,执行getObjectForBeanInstance(),执行FactoryBean的getObject()方法,放入缓存并返回最终bean。

容器事件和事件监听器

ApplicationEventMulticaster提供了事件监听和发布功能。

容器启动的时候,可以获取到所有的事件监听类。

1.  在refresh()中initApplicationEventMulticaster()创建一个事件发布者,并以bean的形式注册到ioc容器中。

2.  在registerListeners()方法里,获取所有实现ApplicationListener接口的类,并添加到事件监听器的set中。

3.  applicationContext启动的最后一步finishRefresh(),会发布一条ContextRefreshedEvent事件。

4.  事件发布后publishEvent(),for循环遍历所有注册到set里的监听器,如果监听器的类是当前事件的实现类,则执行事件。

5.  applicationContext关闭容器后也会发布一个close事件,会销毁所有的单例bean。

AOP

AOP代理工厂:ProxyFactory使用JDK动态代理还是CGLIB动态代理取决于proxyTargetClass。

AOP拦截器链

image.png 以MethodBeforeAdviceInterceptor和AfterReturningAdviceInterceptor为例:

MethodBeforeAdviceInterceptor的invoke()方法先会调advice设定的before()方法,再执行proceed()方法。

AfterReturningAdviceInterceptor的invoke()方法会先执行proceed()方法,再执行定义的afterReturning()方法。

proceed()方法类似递归调用,如果先执行了AfterReturning()方法,会先存入栈中,找下一个inteceptor。直到完成递归调用后,在栈弹出的过程中执行AfterReturning()方法。

因此,通过递归,实现了先执行before()的interceptor再执行调用的method()方法,最后执行afterReturning()方法。

动态代理融入bean的生命周期

在createBean()中,执行resolveBeforeInstantiation()方法,查看beanPostProcessor中是否实现InstantiationAwareBeanPostProcessor接口。有的话直接生成代理对象,并执行前置和后置方法。

包扫描ComponentScan

包扫描在refresh()方法的refreshBeanFactory()中实现。

1.  通过xml获得具体的resource文件后,读入他的字节流。

2.  解析是否有component-scan的标签。

3.  如果有标签则获取base-package标签的内容。

4.  扫描对应包的路径下带有Component.class的所有类,并生成对应的beanDefinition加入到ioc容器里。