先看一下Spring是如何管理Bean
public class TestDemo {
public static void main(String[] args) {
ApplicationContext context=new AnnotationConfigApplicationContext("com.itmck.beans");
UserServiceImpl bean = context.getBean("userServiceImpl",UserServiceImpl.class);
bean.sayHi();
}
}
通过AnnotationConfigApplicationContext 构造函数如下可知:
public class AnnotationConfigApplicationContext {
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);
refresh();
}
}
手写Spring中Bean的实例化过程
我们创建了AnnotationConfigApplicationContext并且拥有一个扫描方法,一个刷新方法(创建Bean方法),还有getBean()方法.简单架子如下所示:
package com.itmck.spring.core;
/**
* 太阳当空照,花儿对我笑
* <p>
* Create by M ChangKe 2021/11/25 10:17
**/
public class AnnotationConfigApplicationContext {
/**
* 通过构造方法传入配置类
*
* @param myConfigClass 配置类
*/
public AnnotationConfigApplicationContext(Class<?> myConfigClass) {
scan(myConfigClass);
refresh();
}
/**
* 扫描配置类
*
* @param myConfigClass 配置类
*/
private void scan(Class<?> myConfigClass) {
}
/**
* 创建Bean
*/
private void refresh() {
}
/**
* 通过BeanName获取Bean对象
*
* @param beanName Bean别名
* @return Bean对象
*/
public Object getBean(String beanName) {
return null;
}
/**
* 通过通过BeanName一级Bean class获取Bean对象
*
* @param beanName Bean别名
* @param tClass bean class类型
* @param <T> 实例泛型
* @return Bean对象
*/
public <T> T getBean(String beanName, Class<T> tClass) {
return tClass.cast(getBean(beanName));
}
}
package com.itmck.spring.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
String value() default "";
}
package com.itmck.spring.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
}
package com.itmck.spring.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 类扫描注解
*
* 太阳当空照,花儿对我笑
* <p>
* Create by M ChangKe 2021/9/11 16:44
**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
String value() default "";
}
package com.itmck.spring.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
String value() default "";
}
扫描的目的就是扫描出BeanDefinition集合.BeanDefinition中包含了Bean类型,是否单例,是否懒加载....等
package com.itmck.spring.core;
/**
* 太阳当空照,花儿对我笑
* <p>
* Create by M ChangKe 2021/9/11 17:28
**/
public class BeanDefinition {
/**
* bean类型
*/
private Class<?> type;
/**
* 是否是单例
*/
private String scope;
/**
* 是否是懒加载
*/
private boolean isLazy;
public Class<?> getType() {
return type;
}
public void setType(Class<?> type) {
this.type = type;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public boolean isLazy() {
return isLazy;
}
public void setLazy(boolean lazy) {
isLazy = lazy;
}
}
scan()扫面得到Bean定义用于Bean的创建,详细代码参考下面完整代码
refresh(),主要是遍历beanDefinitionMap,创建出所有的Bean,详细代码参考下面完整代码
package com.itmck.spring.core;
import com.itmck.spring.annotation.Component;
import com.itmck.spring.annotation.ComponentScan;
import com.itmck.spring.annotation.Scope;
import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
/**
* 太阳当空照,花儿对我笑
* <p>
* Create by M ChangKe 2021/11/25 10:17
**/
public class AnnotationConfigApplicationContext {
/**
* beanDefinitionMap 存放多个Bean定义 其中key为BeanName,value为BeanDefinition
*/
private final Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
/**
* 单例池,如果创建的是单例对象则放入单例池中
*/
private final Map<String, Object> singletonObjects = new HashMap<>(256);
/**
* 通过构造方法传入配置类
*
* @param myConfigClass 配置类
*/
public AnnotationConfigApplicationContext(Class<?> myConfigClass) {
scan(myConfigClass);
refresh();
}
/**
* 扫描配置类
*
* @param myConfigClass 配置类
*/
private void scan(Class<?> myConfigClass) {
if (myConfigClass.isAnnotationPresent(ComponentScan.class)) {
//如果当前配置类上存在注解@ComponentScan,则代表当前类为配置类
ComponentScan componentScan = myConfigClass.getAnnotation(ComponentScan.class);
//获取value内容 com.itmck.mck
String path = componentScan.value();
path = path.replace(".", "/");//将com.itmck.mck-->com/itmck/mck
//获取当前类加载器
ClassLoader classLoader = this.getClass().getClassLoader();
URL resource = classLoader.getResource(path);
assert resource != null;
File file = new File(resource.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
assert files != null;
for (File f : files) {
String absolutePath = f.getAbsolutePath();
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
absolutePath = absolutePath.replace("\\", ".");
Class<?> aClass = null;
try {
//通过类加载器,加载当前类信息
aClass = classLoader.loadClass(absolutePath);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
assert aClass != null;
if (aClass.isAnnotationPresent(Component.class)) {
//如果当前类上存在存在@Component注解
Component component = aClass.getAnnotation(Component.class);
String beanName = component.value();
if ("".equals(beanName)) {
//如果没有给默认值,则使用类的首字母小写
beanName = Introspector.decapitalize(aClass.getSimpleName());
}
//扫描的目的就是获取BeanDefinition
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(aClass);
//判断是否存在Scope注解标记
if (aClass.isAnnotationPresent(Scope.class)) {
Scope scope = aClass.getAnnotation(Scope.class);
String value = scope.value();
beanDefinition.setScope(value);
} else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
}
}
}
}
/**
* 创建Bean
*/
private void refresh() {
//在这里拿到beanDefinitionMap后即可对Bean进行创建
beanDefinitionMap.forEach((beanName, beanDefinition) -> {
if ("singleton".equals(beanDefinition.getScope())) {
try {
Object bean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, bean);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Class<?> aClass = beanDefinition.getType();
Object instance = null;
if (aClass.isAnnotationPresent(Component.class)) {
try {
instance = aClass.getConstructor().newInstance();//无参构造创建Bean
Field[] declaredFields = aClass.getDeclaredFields();
for (Field field : declaredFields) {
String name = field.getName();
field.setAccessible(true);
field.set(instance, getBean(name));
}
} catch (Exception e) {
e.printStackTrace();
}
}
return instance;
}
/**
* 通过BeanName获取Bean对象
*
* @param beanName Bean别名
* @return Bean对象
*/
public Object getBean(String beanName) {
if (!beanDefinitionMap.containsKey(beanName)) {
throw new NullPointerException();
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
//如果是获取的Bean在单例池中存在则从单例池中取,否则新建
if ("singleton".equals(beanDefinition.getScope())) {
Object singletonBean = singletonObjects.get(beanName);
if (singletonBean == null) {
singletonBean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, singletonBean);
}
return singletonBean;
} else {
// 原型Bean
return createBean(beanName, beanDefinition);
}
}
/**
* 通过通过BeanName一级Bean class获取Bean对象
*
* @param beanName Bean别名
* @param tClass bean class类型
* @param <T> 实例泛型
* @return Bean对象
*/
public <T> T getBean(String beanName, Class<T> tClass) {
return tClass.cast(getBean(beanName));
}
}
package com.itmck.one;
import com.itmck.spring.annotation.ComponentScan;
@ComponentScan("com.itmck.one")
public class OneConfig {
}
package com.itmck.one;
import com.itmck.spring.annotation.Autowired;
import com.itmck.spring.annotation.Component;
@Component
public class User {
public void run() {
System.out.println("User#run() is running...");
}
}
package com.itmck.one;
import com.itmck.mck.MyConfig;
import com.itmck.mck.UserA;
import com.itmck.mck.UserB;
import com.itmck.spring.core.AnnotationConfigApplicationContext;
import com.itmck.spring.core.AnnotationConfigApplicationContext2;
/**
* 太阳当空照,花儿对我笑
* <p>
* Create by M ChangKe 2021/11/24 9:36
**/
public class TestDemo2 {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
User user = applicationContext.getBean("user", User.class);
user.run();
}
}
运行结果 User#run() is running...
注:上述代码是针对单个Bean进行扫描以及创建的简单流程梳理,但spring中远不止这些.
什么是循环依赖?
循环依赖就是A依赖B,B依赖A,互相依赖.主要分为一个类之间,两个类,多个类之间的依赖
Spring在创建Bean的时候是如何解决循环依赖问题?
spring中使用三级缓存解决循环依赖
package com.itmck.mck;
import com.itmck.spring.annotation.Autowired;
import com.itmck.spring.annotation.Component;
/**
* 太阳当空照,花儿对我笑
* <p>
* Create by M ChangKe 2021/9/11 18:08
**/
@Component
public class UserA {
@Autowired
private UserB userB;
public void run() {
System.out.println("UserA");
}
//省略get/set
}
package com.itmck.mck;
import com.itmck.spring.annotation.Autowired;
import com.itmck.spring.annotation.Component;
/**
* 太阳当空照,花儿对我笑
* <p>
* Create by M ChangKe 2021/9/11 18:08
**/
@Component
public class UserB {
@Autowired
private UserA userA;
public void run(){
System.out.println("UserB");
}
//略get/set
}
修改createBean()方法是关键.因为A依赖B,在创建A的时候给A属性赋值,这时需要创建B.然后创建B又依赖到A....循环往复.怎么办????
private Object createBean(String beanName, BeanDefinition beanDefinition) {
//使用一级缓存解决循环依赖
//**在这里先判断一级缓存中是否存在,这里是解决循环依赖的关键,添加一个递归出口,防止无限递归**
Object singleton = getSingleton(beanName);
if (singleton != null) {
return singleton;
}
Class<?> aClass = beanDefinition.getType();
Object instance = null;
if (aClass.isAnnotationPresent(Component.class)) {
try {
instance = aClass.getConstructor().newInstance();//无参构造创建Bean
singletonObjects.put(beanName,instance);//将instance放入一级缓存
Field[] declaredFields = aClass.getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
//**在这里调用自身方法进行递归操作获取bean**
field.set(instance,createBean(field.getName(), beanDefinitionMap.get(field.getName())));
}
} catch (Exception e) {
e.printStackTrace();
}
}
return instance;
}
public Object getSingleton(String beanName) {
if (singletonObjects.containsKey(beanName)) {
return singletonObjects.get(beanName);
}
return null;
}
package com.itmck;
import com.itmck.mck.MyConfig;
import com.itmck.mck.UserA;
import com.itmck.mck.UserB;
import com.itmck.one.OneConfig;
import com.itmck.one.User;
import com.itmck.spring.core.AnnotationConfigApplicationContext;
import com.itmck.spring.core.AnnotationConfigApplicationContext2;
/**
* 太阳当空照,花儿对我笑
* <p>
* Create by M ChangKe 2021/11/24 9:36
**/
public class MckSpringApplication {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext2 applicationContext = new AnnotationConfigApplicationContext2(MyConfig.class);
UserA userA = applicationContext.getBean("userA", UserA.class);
UserB userB1 = userA.getUserB();
System.out.println("UserA#userB.run()");
userB1.run();
UserB userB = applicationContext.getBean("userB", UserB.class);
UserA userA1 = userB.getUserA();
System.out.println("UserB#userA.run()");
userA1.run();
}
}
结果如下,表示循环依赖已经解决
UserA#userB.run()
UserB
UserB#userA.run()
UserA
现在看上去一级缓存已经能够解决循环依赖问题,如果是多线程环境下:假如现有2个线程,第一个线程在创建beanA的时候,属性赋值后加入一级缓存,第二个线程去getBeanA,拿到的是不完整的beanA。所以需要二级缓存
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
注意:earlySingletonObjects.put(beanName, instance)与singletonObjects.put(beanName, instance)位置
private Object createBean(String beanName, BeanDefinition beanDefinition) {
//使用一级缓存解决循环依赖
//在这里先判断一级缓存中是否存在,这里是解决循环依赖的关键,添加一个递归出口,防止无限递归
Object singleton = getSingleton(beanName);
if (singleton != null) {
return singleton;
}
Class<?> aClass = beanDefinition.getType();
Object instance = null;
if (aClass.isAnnotationPresent(Component.class)) {
try {
instance = aClass.getConstructor().newInstance();//无参构造创建Bean
earlySingletonObjects.put(beanName, instance);//这里新增二级缓存存放新鲜反射出来的纯净Bean
Field[] declaredFields = aClass.getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
field.set(instance, createBean(field.getName(), beanDefinitionMap.get(field.getName())));//在这里调用自身方法进行递归操作获取bean
}
} catch (Exception e) {
e.printStackTrace();
}
}
//初始化在这里
//init------
singletonObjects.put(beanName, instance);//将instance放入一级缓存,这里的Bean是完成了属性赋值,初始化等完整的单例Bean
return instance;
}
/**
* 通过判断
*
* @param beanName Bean别名
* @return Bean对象
*/
public Object getSingleton(String beanName) {
if (singletonObjects.containsKey(beanName)) {
return singletonObjects.get(beanName);
}else if (earlySingletonObjects.containsKey(beanName)){
//新增二级缓存后,一级缓存没有从二级缓存中取
return earlySingletonObjects.get(beanName);
}
return null;
}
最后运行结果与上述一致.
我们在创建bean 的时候, 会有很多Bean的后置处理器BeanPostProcessor. 如果有AOP, 会在什么时候创建呢? 在初始化以后, 调用BeanPostProcessor创建动态代理.
结合上面的代码, 我们想一想, 其实在初始化以后创建动态代理就晚了. 为什么呢? 因为, 如果有循环依赖, 在初始化之后才调用, 那就不是动态代理. 其实我们这时候应该在实例化之后, 放入到二级缓存之前调用. 如果判断有循环依赖此时进行AOP,那么最佳位置应该是在判断二级缓存存在说明是循环依赖,此时进行aop然后将新的实例放入二级缓存
修改后代码如下:
public Object getSingleton(String beanName) {
if (singletonObjects.containsKey(beanName)) {
return singletonObjects.get(beanName);
}else if (earlySingletonObjects.containsKey(beanName)){
//新增二级缓存后,一级缓存没有从二级缓存中取
/**
* 第一次创建bean是正常的instanceBean. 他并不是循环依赖. 第二次进来判断, 这个bean已经存在了, 就说明是循环依赖了
* 这时候通过动态代理创建bean. 然后将这个bean在放入到二级缓存中覆盖原来的instanceBean.
* 这样我们在循环依赖的时候就完成了AOP的创建. 这是在二级缓存里创建的AOP
*/
Object instance = new CglibProxyBeanPostProcessor().getEarlyBeanReference(earlySingletonObjects.get(beanName), beanName);
earlySingletonObjects.put(beanName, instance);
return earlySingletonObjects.get(beanName);
}
return null;
}
package com.itmck.mck;
import com.itmck.spring.annotation.Component;
import com.itmck.spring.core.SmartInstantiationAwareBeanPostProcessor;
import com.itmck.spring.proxy.MyEnhancer;
import com.itmck.spring.proxy.MyProxy;
import net.sf.cglib.proxy.Enhancer;
/**
* 太阳当空照,花儿对我笑
* <p>
* Create by M ChangKe 2021/9/11 18:08
**/
@Component
public class CglibProxyBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
// 假设A被切点命中 需要创建代理 @PointCut("execution(* *..InstanceA.*(..))")
/**
* 这里, 我们简单直接判断bean是不是InstanceA实例, 如果是, 就创建动态代理.
* 这里没有去解析切点, 解析切点是AspectJ做的事.
*/
if (bean instanceof UserA) {
MyEnhancer myEnhancer = new MyEnhancer(new MyProxy(),bean);
Enhancer enhancer = myEnhancer.getEnhancer();
bean = enhancer.create();
}
return bean;
}
}
使用cglib代理需要引入pom
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
package com.itmck.spring.proxy;
import net.sf.cglib.proxy.Enhancer;
/**
* 太阳当空照,花儿对我笑
* <p>
* Create by M ChangKe 2021/11/25 15:11
**/
public class MyEnhancer {
private final MyProxy myProxy;
private final Object object;
public MyEnhancer(MyProxy myProxy, Object object) {
this.myProxy = myProxy;
this.object = object;
}
public Enhancer getEnhancer(){
Enhancer enhancer = new Enhancer(); // 通过CGLIB动态代理获取代理对象的过程
enhancer.setSuperclass(object.getClass()); // 设置enhancer对象的父类
enhancer.setCallback(myProxy); // 设置enhancer的回调对象
return enhancer;
}
}
package com.itmck.spring.proxy;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class MyProxy implements MethodInterceptor {
/**
*
* @param o cglib生成的代理对象
* @param method 被代理对象的方法
* @param objects 传入方法的参数
* @param methodProxy 代理的方法
* @return
* @throws Throwable
*/
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("这里可以插入执行关键代码之前的逻辑");
Object o1 = methodProxy.invokeSuper(o, objects);//关键代码:
System.out.println("这里可以插入执行关键代码之后的逻辑");
return o1;
}
}
此时运行代码结果
UserA#userB.run()
UserB
UserB#userA.run()
这里可以插入执行关键代码之前的逻辑
UserA
这里可以插入执行关键代码之后的逻辑
到这里可以发现使用二级缓存就可以解决循环依赖中Aop的问题.那么为什Spring使用了三级缓存?
三级缓存是为了单一职责 如果在getBean的时候写,不符合标准。后置处理器是在bean的创建过程中去给它增强的
在createBean中实例化之后进行保存ObjectFactory 到三级缓存singletonFactories
private Object createBean(String beanName, BeanDefinition beanDefinition) {
//使用一级缓存解决循环依赖
//在这里先判断一级缓存中是否存在,这里是解决循环依赖的关键,添加一个递归出口,防止无限递归
Object singleton = getSingleton(beanName);
if (singleton != null) {
return singleton;
}
// 正在创建
singletonsCurrentlyInCreation.add(beanName);
Class<?> aClass = beanDefinition.getType();
Object instance = null;
if (aClass.isAnnotationPresent(Component.class)) {
try {
instance = aClass.getConstructor().newInstance();//无参构造创建Bean
//在这里直接进行aop不合理,因为没有进行判断,所以要先判断是否需要进行代理,如果需要才进行aop,在哪里判断?
//当有循环依赖的时候,二级缓存不为null,所以在getSingleton()中判断
//instance = new JdkProxyBeanPostProcessor().getEarlyBeanReference(instance, beanName);
//实例化之后保 级缓存就是存函数接口的
singletonFactories.put(beanName,() -> new CglibProxyBeanPostProcessor().getEarlyBeanReference(earlySingletonObjects.get(beanName), beanName));
earlySingletonObjects.put(beanName, instance);//这里新增二级缓存存放新鲜反射出来的纯净Bean
Field[] declaredFields = aClass.getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
field.set(instance, createBean(field.getName(), beanDefinitionMap.get(field.getName())));//在这里调用自身方法进行递归操作获取bean
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 第四步: 初始化
* 初始化就是设置类的init-method.这个可以设置也可以不设置. 我们这里就不设置了
*/
//正常的代理实在初始化之后,就是这里进行,但是如果存在循环依赖必须在实例化之后进行
//instance = new JdkProxyBeanPostProcessor().getEarlyBeanReference(instance, beanName);
// 由于递归完后A 还是原实例,, 所以要从二级缓存中拿到proxy 。
if (earlySingletonObjects.containsKey(beanName)) {
instance = earlySingletonObjects.get(beanName);
}
//将instance放入一级缓存,这里的Bean是完成了属性赋值,初始化等完整的单例Bean
singletonObjects.put(beanName, instance);
return instance;
}
public Object getSingleton(String beanName) {
// 先从一级缓存中拿
Object bean = singletonObjects.get(beanName);
// 说明是循环依赖
if (bean == null && singletonsCurrentlyInCreation.contains(beanName)) {
bean = earlySingletonObjects.get(beanName);
// 如果二级缓存没有就从三级缓存中拿
if (bean == null) {
// 从三级缓存中拿
ObjectFactory<?> factory = singletonFactories.get(beanName);
if (factory != null) {
try {
bean = factory.getObject(); // 拿到动态代理
earlySingletonObjects.put(beanName, bean);
//然后从二级缓存移除singletonFactory
this.singletonFactories.remove(beanName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return bean;
}
package com.itmck.spring.core;
import com.itmck.mck.CglibProxyBeanPostProcessor;
import com.itmck.spring.annotation.Component;
import com.itmck.spring.annotation.ComponentScan;
import com.itmck.spring.annotation.Scope;
import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* 太阳当空照,花儿对我笑
* <p>
* Create by M ChangKe 2021/11/25 10:17
*
* 模拟spring读取配置文件以及创建Bean,引入三级缓存目的,存放ObjectFactory,单一自责
*
**/
public class AnnotationConfigApplicationContext3 {
/**
* beanDefinitionMap 存放多个Bean定义 其中key为BeanName,value为BeanDefinition
*/
private final Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
/**
* 单例池,如果创建的是单例对象则放入单例池中
*/
private final Map<String, Object> singletonObjects = new HashMap<>(256);
//早期Bean,还未被初始化以及属性赋值
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
// 三级缓存
public final Map<String, ObjectFactory<?>> singletonFactories = new ConcurrentHashMap<>();
//循环依赖标识
public final Set<String> singletonsCurrentlyInCreation = new HashSet<>();
/**
* 通过构造方法传入配置类
*
* @param myConfigClass 配置类
*/
public AnnotationConfigApplicationContext3(Class<?> myConfigClass) {
scan(myConfigClass);
refresh();
}
/**
* 扫描配置类
*
* @param myConfigClass 配置类
*/
private void scan(Class<?> myConfigClass) {
if (myConfigClass.isAnnotationPresent(ComponentScan.class)) {
//如果当前配置类上存在注解@ComponentScan,则代表当前类为配置类
ComponentScan componentScan = myConfigClass.getAnnotation(ComponentScan.class);
//获取value内容 com.itmck.mck
String path = componentScan.value();
path = path.replace(".", "/");//将com.itmck.mck-->com/itmck/mck
//获取当前类加载器
ClassLoader classLoader = this.getClass().getClassLoader();
URL resource = classLoader.getResource(path);
assert resource != null;
File file = new File(resource.getFile());
if (file.isDirectory()) {
File[] files = file.listFiles();
assert files != null;
for (File f : files) {
String absolutePath = f.getAbsolutePath();
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
absolutePath = absolutePath.replace("\\", ".");
Class<?> aClass = null;
try {
//通过类加载器,加载当前类信息
aClass = classLoader.loadClass(absolutePath);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
assert aClass != null;
if (aClass.isAnnotationPresent(Component.class)) {
//如果当前类上存在存在@Component注解
Component component = aClass.getAnnotation(Component.class);
String beanName = component.value();
if ("".equals(beanName)) {
//如果没有给默认值,则使用类的首字母小写
beanName = Introspector.decapitalize(aClass.getSimpleName());
}
//扫描的目的就是获取BeanDefinition
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(aClass);
//判断是否存在Scope注解标记
if (aClass.isAnnotationPresent(Scope.class)) {
Scope scope = aClass.getAnnotation(Scope.class);
String value = scope.value();
beanDefinition.setScope(value);
} else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
}
}
}
}
/**
* 创建Bean
*/
private void refresh() {
//在这里拿到beanDefinitionMap后即可对Bean进行创建
beanDefinitionMap.forEach((beanName, beanDefinition) -> {
if ("singleton".equals(beanDefinition.getScope())) {
try {
createBean(beanName, beanDefinition);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private Object createBean(String beanName, BeanDefinition beanDefinition) {
//使用一级缓存解决循环依赖
//在这里先判断一级缓存中是否存在,这里是解决循环依赖的关键,添加一个递归出口,防止无限递归
Object singleton = getSingleton(beanName);
if (singleton != null) {
return singleton;
}
// 正在创建
singletonsCurrentlyInCreation.add(beanName);
Class<?> aClass = beanDefinition.getType();
Object instance = null;
if (aClass.isAnnotationPresent(Component.class)) {
try {
instance = aClass.getConstructor().newInstance();//无参构造创建Bean
Object finalInstance = instance;
singletonFactories.put(beanName, (ObjectFactory<?>)()-> new CglibProxyBeanPostProcessor().getEarlyBeanReference(finalInstance, beanName));
earlySingletonObjects.put(beanName, instance);//这里新增二级缓存存放新鲜反射出来的纯净Bean
Field[] declaredFields = aClass.getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
field.set(instance, createBean(field.getName(), beanDefinitionMap.get(field.getName())));//在这里调用自身方法进行递归操作获取bean
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 第四步: 初始化
* 初始化就是设置类的init-method.这个可以设置也可以不设置. 我们这里就不设置了
*/
// 由于递归完后A 还是原实例,, 所以要从二级缓存中拿到proxy 。
if (earlySingletonObjects.containsKey(beanName)) {
instance = earlySingletonObjects.get(beanName);
}
//将instance放入一级缓存,这里的Bean是完成了属性赋值,初始化等完整的单例Bean
singletonObjects.put(beanName, instance);
return instance;
}
public Object getSingleton(String beanName) {
// 先从一级缓存中拿
Object bean = singletonObjects.get(beanName);
// 说明是循环依赖
if (bean == null && singletonsCurrentlyInCreation.contains(beanName)) {
bean = earlySingletonObjects.get(beanName);
// 如果二级缓存没有就从三级缓存中拿
if (bean == null) {
// 从三级缓存中拿
ObjectFactory<?> factory = singletonFactories.get(beanName);
if (factory != null) {
try {
bean = factory.getObject(); // 拿到动态代理
earlySingletonObjects.put(beanName, bean);
//然后从二级缓存移除singletonFactory
this.singletonFactories.remove(beanName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return bean;
}
public Object getBean(String beanName) {
if (!beanDefinitionMap.containsKey(beanName)) {
throw new NullPointerException();
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
//如果是获取的Bean在单例池中存在则从单例池中取,否则新建
if ("singleton".equals(beanDefinition.getScope())) {
Object singletonBean = singletonObjects.get(beanName);
if (singletonBean == null) {
singletonBean = createBean(beanName, beanDefinition);
}
return singletonBean;
} else {
// 原型Bean
return createBean(beanName, beanDefinition);
}
}
/**
* 通过通过BeanName一级Bean class获取Bean对象
*
* @param beanName Bean别名
* @param tClass bean class类型
* @param <T> 实例泛型
* @return Bean对象
*/
public <T> T getBean(String beanName, Class<T> tClass) {
return tClass.cast(getBean(beanName));
}
}
运行结果与上述一致
这样以来.职责明确.一级缓存单例池,二级缓存纯净Bean,三级缓存存放用于创建代理Bean的ObjectFactory.
面试题: 在创建bean的时候, 在哪里创建的动态代理, 这个应该怎么回答呢?
很多人会说在初始化之后, 或者在实例化之后.
其实更严谨的说, 有两种情况: 第一种是在初始化之后调用 . 第二种是出现了循环依赖, 会在实例化之后调用
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。