:::info
:::




springmvc中父子容器
一二级缓存 缓存的对象是一样的,三级缓存不一样
单例才能解决循环依赖,prototype无法解决,直接报错
解决循环依赖
循环依赖有两种,一种是构造器循环依赖,另一种是set循环依赖。构造器循环依赖解决不了,在spring里,构造器和实例化是一起操作的,而实例化和初始化两个操作是分开的,所以可以解决set循环依赖
解决循环依赖关键代码
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isTraceEnabled()) {logger.trace("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {Object exposedObject = bean;if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);}}}return exposedObject;}protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {Assert.notNull(singletonFactory, "Singleton factory must not be null");synchronized (this.singletonObjects) {if (!this.singletonObjects.containsKey(beanName)) {this.singletonFactories.put(beanName, singletonFactory);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}}}
DefaultListableBeanFactory
loadBeanDeifinitions
很多个重载方法,执行顺序为
String[]->String->Resoure[]->Resource
// 此处获取xml文件的document对象,这个解析过程是由documentLoader完成的,从String[] -string-Resource[]- resource,最终开始将resource读取成一个document文档,根据文档的节点信息封装成一个个的BeanDefinition对象Document doc = doLoadDocument(inputSource, resource);
registerBeanDefinitions 创建对象封装到到Beandefinition
如何拓展实现自定义属性编辑器
AspectJ
实现分为 运行期织入 类加载器织入 编译器织入
AspectJWeavingEnabler
BeanFactoryPostProcessor
ConfigurationClassPostProcessor
以Springboot 的自动装配为例
自动装配大致原理是默认识别starter的META-INF/spring.factories 文件里面的值,核心是通过@Import注解去实现的,那@Import是如何实现的呢
ConfigurationClassPostProcessor会解析一些常用的注解 如@Component @ComponentScans @PropertySources @ImportResource @Import,这其中 @Import 就包含了处理
ImportSelector, ImportBeanDefinitionRegistrar, DeferredImportSelector

监听器
实例化
五种实例化方式
InstantiationAwareBeanPostProcessor 继承自 BeanPostProcessor
是在BeanPostProcessor阶段完成实例化
例子:
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {System.out.println("beanName:"+beanName+"----执行postProcessBeforeInstantiation方法");if (beanClass == BeforeInstantiation.class){// Enhancer enhancer = new Enhancer();// enhancer.setSuperclass(beanClass);// enhancer.setCallback(new MyMethodInterceptor());// BeforeInstantiation beforeInstantiation = (BeforeInstantiation) enhancer.create();// System.out.println("创建代理对象:"+beforeInstantiation);return new BeforeInstantiation();}return null;}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {System.out.println("beanName:"+beanName+"----执行postProcessAfterInstantiation方法");return false;}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("beanName:"+beanName+"----执行postProcessBeforeInitialization方法");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("beanName:"+beanName+"----执行postProcessAfterInitialization方法");return bean;}@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {System.out.println("beanName:"+beanName+"----执行postProcessProperties方法");return pvs;}}
public class BeforeInstantiation {public void doSomeThing(){System.out.println("执行do some thing....");}}
<bean id="beforeInstantiation" class="com.mashibing.resolveBeforeInstantiation.BeforeInstantiation"></bean><bean id="myInstantiationAwareBeanPostProcessor" class="com.mashibing.resolveBeforeInstantiation.MyInstantiationAwareBeanPostProcessor"></bean>
public class Test {public static void main(String[] args) {ApplicationContext ac = new ClassPathXmlApplicationContext("resolveBeforeInstantiation.xml");BeforeInstantiation bean = ac.getBean(BeforeInstantiation.class);bean.doSomeThing();}}
关键源码在 createBean()方法中的
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);/** resolveBeforeInstantiation 方法会执行继承了 InstantiationAwareBeanPostProcessor类前/后* 处理器*/
反射
BeanWapper Bean包装类
这个是用来做什么的呢?其实也很简单,现在创建出一个空对象之后,还要对空对像的属性进行填充吧,那属性填充的时候是不是要做类型转换(因为我们从xml文件读取的数据肯定是字符串类型)。这里我们看它的继承就知道了:
TypeConverter:类型转换器
PropertyEditorRegistry:
PropertyAccessor:
applyMergedBeanDefinitionPostProcessors
factory-method
FactoryBean
Supplier
SmartInstantiationAwareBeanPostProcessor
作用:
- 预测类型
- 决定当前的构造器
- 处理循环依赖的时候需要使用
getMergedLocalBeanDefinition 合并BeanDefinition父子信息
在执行invokeBFPP方法时,getBeanForType()方法第一次执行getMergedLocalBeanDefinition(),将得到的RootBeanDefinition放到缓存中
// 合并父类BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

源码细节在 doCreatebean()-> createBeanInstance()-> Supplier<?> instanceSupplier = mbd.getInstanceSupplier()
lookup-method标签
解决单例引用原型
名词解释:
prototype: 原型对象,被被标识的bean,在get的时候会是一个新的对象
验证例子如:
spring配置文件为
<bean id="apple" class="com.mashibing.methodOverrides.lookup.Apple" ><property name="banana" ref="banana"></property></bean><bean id="banana" class="com.mashibing.methodOverrides.lookup.Banana" scope="prototype"></bean>
设置apple为单例,且apple中关联的的banana为prototype,那在获取bean的时候,banana只是同一个对象,如:
ApplicationContext ac = new ClassPathXmlApplicationContext("methodOverride.xml");Apple bean = ac.getBean(Apple.class);System.out.println(bean.getBanana());Apple bean2 = ac.getBean(Apple.class);System.out.println(bean2.getBanana());// 输出// com.mashibing.methodOverrides.lookup.Banana@67784306// com.mashibing.methodOverrides.lookup.Banana@67784306
可以看出, apple中的banana属性在这里是无法实现每次都获取新的banana对象。
而使用looku-method,如
<bean id="apple" class="com.mashibing.methodOverrides.lookup.Apple" ><lookup-method name="getBanana" bean="banana"></lookup-method></bean><bean id="banana" class="com.mashibing.methodOverrides.lookup.Banana" scope="prototype"></bean>
在代码不变情况下,输出为
com.mashibing.methodOverrides.lookup.Banana@11758f2acom.mashibing.methodOverrides.lookup.Banana@e720b71
就可以实现
replace-method
初始化
循环依赖

如果单纯为了解决循环依赖,那么使用二级缓存足够解决问题了。三级缓存存在的意义是为了代理,如果没有代理对象,二级缓存足以解决问题1
填充属性 populateBean
t

