一.作用
- 1.为了保证动态代理只创建一次
- 2.如果只有二级缓存,出现多次循环依赖,例如A<–>B 和A<–>C,此时会创建多个代理A
二.代码示例
package com.learning.circulardependency;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Author wangyouhui
* @Description 循环依赖-二级缓存
**/
public class MyApplicationContext3 {
// 单例 解决线程安全: 双重检查锁
private Map<String, BeanDefinition> beanDefinitionMap = new LinkedHashMap<>();
// 一级缓存 单例池 问题:早期的bean和完整bean放在一起,会出现并发下获取不完的bean
// 所有完整的bean
private final Map<String,Object> singletonObjects = new ConcurrentHashMap<>();
// 二级缓存 为了解决循环依赖,并且能够解决并发下获取不完整bean的性能问题,利用双重检查锁+二级缓存
private final Map<String,Object> earlySingletonObjects = new ConcurrentHashMap<>();
// 三级缓存 为了保证动态代理只创建一次(如果只有二级缓存,出现多次循环依赖,例如A<->B A<->C,此时会创建多个代理A)
private final Map<String,Object> factoriesSingletonObjects = new ConcurrentHashMap<>();
public MyApplicationContext3() throws Exception{
// 加载ioc容器:创建所有的Bean
refresh();
}
// ioc容器加载
private void refresh() throws Exception{
// 解析配置 注册BeanDefinition
loadBeanDefinitions();
// 创建所有单例Bean
finishBeanFactoryInitialization();
}
/**
* 创建所有的Bean
*/
private void finishBeanFactoryInitialization() throws Exception{
for (String beanName : beanDefinitionMap.keySet()) {
getBean(beanName);
}
}
/**
* 根据beanName创建Bean
*/
public Object getBean(String beanName) throws Exception {
// 判断Bean是否已经创建好。如果已经创建好了就直接返回,如果没有创建就开始创建
Object bean = getSingleton(beanName);
if(bean != null){
return bean;
}
synchronized (singletonObjects) {
// 双重检查锁,解决并发获取不完整的bean
if(singletonObjects.containsKey(beanName)){
return singletonObjects.get(beanName);
}
//1. 实例化
RootBeanDefinition beanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
Class<?> beanClass = beanDefinition.getBeanClass();
bean = beanClass.newInstance();
//2. 将代理的bean放入二级缓存
earlySingletonObjects.put(beanName, bean);
//3. 属性注入
Field[] declaredFields = beanClass.getDeclaredFields();
for (Field field : declaredFields) {
// 拿到属性的Autowired注解
Autowired autowired = field.getAnnotation(Autowired.class);
// 如果有@Autowired,就要进行注入
if (autowired != null) {
// spring中先根据类型找,如果类型都一样,再根据名字找
// 这里按名字找
String name = field.getName();
Object dependentBean = getBean(name);
// 设置下访问权限
field.setAccessible(true);
field.set(bean, dependentBean);
}
}
//4. 初始化
if (bean instanceof InitializingBean) {
InitializingBean initializingBean = (InitializingBean) bean;
initializingBean.afterPropertiesSet();
}
// 5.将bean放入一级缓存
// 再次获取代理bean 为了解决如果在循环依赖中创建了动态代理,需要拿到循环依赖中的proxy对象
Object beanProxy = getSingleton(beanName);
singletonObjects.put(beanName, beanProxy);
// 6.一级缓存中的bean创建完后,将二级缓存中的去掉
earlySingletonObjects.remove(beanName);
factoriesSingletonObjects.remove(beanName);
}
return bean;
}
/**
* 创建Bean是否创建
* @param beanName
*/
private Object getSingleton(String beanName) {
// 一级缓存中有则返回,否则从二级缓存中拿
if(singletonObjects.containsKey(beanName)){
return singletonObjects.get(beanName);
}
synchronized (singletonObjects){
// 三级缓存
if(factoriesSingletonObjects.containsKey(beanName)){
return factoriesSingletonObjects.get(beanName);
}
// 二级缓存
// 所有的bean实例化后就创建proxy, 应该判断只有出现循环依赖才创建proxy
if(earlySingletonObjects.containsKey(beanName)){
Object bean = earlySingletonObjects.get(beanName);
Object beanProxy = new JdkProxyBeanPostProcessor().getEarlyBeanReference(bean, beanName);
factoriesSingletonObjects.put(beanName, beanProxy);
return beanProxy;
}
}
return null;
}
/**
* 根据配置信息创建BeanDefinition 会根据配置信息动态创建
*/
private void loadBeanDefinitions() {
// 创建A BeanDefition
RootBeanDefinition aBeanDefinition = new RootBeanDefinition(InstanceA.class);
// 创建B BeanDefinition
RootBeanDefinition bBeanDefinition = new RootBeanDefinition(InstanceB.class);
beanDefinitionMap.put("instanceA", aBeanDefinition);
beanDefinitionMap.put("instanceB", bBeanDefinition);
}
public static void main(String[] args) throws Exception {
MyApplicationContext3 context = new MyApplicationContext3();
InstanceA instanceA = (InstanceA)context.getBean("instanceA");
System.out.println(instanceA);
}
}
package com.learning.circulardependency;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Author wangyouhui
* @Description jdk动态代理
**/
public class JdkDynamicProxy implements InvocationHandler {
private Object target;
public JdkDynamicProxy(Object target) {
this.target = target;
}
public <T> T getProxy(){
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy增强");
return method.invoke(target, args);
}
}
package com.learning.circulardependency;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
/**
* @Author wangyouhui
* @Description TODO
**/
public class JdkProxyBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
// 假设InstanceA被切点命中,需要创建代理 @PointCut(execution...)
if(bean instanceof InstanceA){
JdkDynamicProxy jdkDynamicProxy = new JdkDynamicProxy(bean);
}
return null;
}
}