上面这个图呢是我自己画出来的总结图:(可以看下面我写的spring简易版代码就懂了)
我们可以知道当你使用spring的时候需要些一些配置类啊什么的那么我们是怎么去拿到的呢,
- 首先我们有一个BeanDefinitionRead去解析你的xml配置文件然后读成BeanDefintion也可以理解为Bean的定义信息,那么拿到定义信息的时候呢我们下一步就是去实例化了,但是注意了这里并不是正在去走实例化,在走实例化的过程中我们需要一个工厂也就是BeanFactory然后工厂利用反射拿到信息,在这之前呢我们BeanFactoryPostProcessor一个增强器图上面我也写了笔记说是获取信息的时候发现需要人为修改一些信息的时候,我们就可以在这里操作了然后再通过工厂去实例化,
- 在实例化的过程中我们还有一个BeanPostProcessor增强器也是可以做一些操作的接下来就是真正的实例化了,
- 在实例化过后我们就是初始化但是在初始化前后呢也有两个方法一个Before一个After但是区别是Before是在初始化之前执行After是在初始化之后执行这里不要搞混了,
- 完成初始化之后就是真正的Bean了。
package com.project.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class A {
@Autowired
private B b;
public void say(){
b.sayHello();
}
}
package com.project.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class B {
@Autowired
private A a;
public void sayHello(){
a.say();
}
}
首先这里重点我要讲的是循环依赖:
循环依赖是什么呢,就是当a在创建bean的时候注入了b,而且在a中调用了b,然后我们依赖就会提前创建b属性,但是在c中呢也调用了a,就导致a还没有创建完就调用b,然后再创建b中又去调用了a从此生成循环依赖:那么底层解决方法是什么呢,其实图上面也说了,那我就在详细的说明一下:
- 当类通过构造方法的时候他会生成一个普通对象并且会放入到三级缓存中,但只是生成一个lambde不会执行只是生成
- 在普通对象发现有依赖注入那么首先会去创建需要依赖注入的对象
- 如果是正常的情况下我们会先去单例池中找
- 如果没有找到那么就正常的CreateBean创建Bean然后再放入单例池
- 如果出现循环依赖,在循环依赖的情况下我们在创建依赖对象的时候发现CreateSet就说明是循环依赖了那么我们底层会先去放入到二级缓存中(earlySingletonObjects--->是一个Map),但是在放入二级缓存中呢我们会去查找二级缓存有没有这个对象在二级缓存如果没有的话我们就去查找三级缓存(singletonFactories),这个时候会执行一开始的lambde对象如果找到了那就返回但是这里要考虑到一个情况如果你是开起来aop那么在这里他会生成代理对象放入到二级缓存,如果没有开启aop的话就不会生成代理对象而是生成普通对象放入到二级缓存中,然后二级缓存在把对象放入到单例池中。
依赖注入不正常情况下,比如加了sycn注解或者两个对象的构造器互相调用那么我们的解决方法是添加lazy注解,如果不加就会报错
这里呢也分享一个面试问题:就是说二级循环二级也能解决,为什么需要三级缓存?
答案呢是:二级缓存只能解决没有aop的循环依赖当有aop的时候就需要三级缓存了。
上面这个图呢是我耗时一个上午画出来的一个详细版的spring流程图也是对应的底层十三个方法的详细解说版本的图片,制作不易请好好品一品。
这里呢我们可以先创建一个spring工程然后写一个对象和一个配置类写一个启动类
package com.project.dao;
public interface UserDao {
public void update();
}
@Test
public void testBean1() {
// 加载spring配置文件
ApplicationContext Context = new ClassPathXmlApplicationContext("bean2.xml");
// 获取配置创建的对象
UserService userService = Context.getBean("userService", UserService.class);
userService.add();
}
这里我们是在ApplicationContext Context = new ClassPathXmlApplicationContext("bean2.xml");这个地方打断点的然后进去:一直走到refresh方法然后点进去就能看见十三个方法了。那么这里呢如果要详细的说的话实在是太耗费打字了实在是太细了所以呢大家看图就行看图就行,通俗易懂。
嗯。。这里代码稍微有点多,我就不放那么多了就把核心的代码放出来如果您有需要的话呢可以在评论区留个言我看见了的话会把源码发给您的,感谢支持
package com.project.spring;
import java.beans.Introspector;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
public class ApplicationContext {
private Class configClass;
private ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap<>();
private ConcurrentHashMap singletonObjects = new ConcurrentHashMap<>();
private ArrayList beanPostProsessorArrayList = new ArrayList<>();
// 扫描
public ApplicationContext(Class configClass){
this.configClass = configClass;
if (configClass.isAnnotationPresent(ComponentScan.class)) {
ComponentScan configClassAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
// 扫描路径
String path = configClassAnnotation.value();
// 截取0到第一个.的位置
String pathFirstName = path.substring(0,path.indexOf("."));
// 把路径中的.替换成/
path = path.replace(".","/");
// 类加载器
ClassLoader classLoader = ApplicationContext.class.getClassLoader();
// 获取路径
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
if (file.isDirectory()){
File[] files = file.listFiles();
for (File f : files) {
// 获取绝对路径 .class文件
String fileName = f.getAbsolutePath();
if (fileName.endsWith(".class")) {
String className = fileName.substring(fileName.indexOf(pathFirstName), fileName.indexOf(".class"));
className = className.replace("\\",".");
try {
Class> aClass = classLoader.loadClass(className);
// 判断是否是bean
if (aClass.isAnnotationPresent(Component.class)){
// 判断是否实现BeanPostProsessor
if (BeanPostProsessor.class.isAssignableFrom(aClass)){
// 直接实例化
BeanPostProsessor instance = (BeanPostProsessor) aClass.newInstance();
beanPostProsessorArrayList.add(instance);
}
// 拿到注解
Component component = aClass.getAnnotation(Component.class);
// 拿到注解的名字
String beanName = component.value();
// 实现默认首字母小写
if (beanName.equals("")){
beanName = Introspector.decapitalize(aClass.getSimpleName());
}
System.out.println(beanName);
// 先创建bean信息
BeanDefinition beanDefinition = new BeanDefinition();
// 设置类型
beanDefinition.setClazz(aClass);
if (aClass.isAnnotationPresent(Scope.class)){
// 判断是否有注解 有的话就拿到注解的名字并且设置到BeanDefinition中
Scope annotation = aClass.getAnnotation(Scope.class);
// 查看scope上面是否有值 没有就还是单例
if (annotation.value().equals("")){
// 没有的话就默认设置单例
beanDefinition.setType("singleton");
}else {
beanDefinition.setType(annotation.value());
}
}else {
// 没有的话就默认设置单例
beanDefinition.setType("singleton");
}
// 放入到map中
concurrentHashMap.put(beanName,beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
}
}
// 循环拿到bean
for (String beanName : concurrentHashMap.keySet()) {
// 拿到bean定义信息
BeanDefinition beanDefinition = concurrentHashMap.get(beanName);
// 如果是单例就创建然后放入单例池
if (beanDefinition.getType().equals("singleton")){
Object bean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName,bean);
}else {
// 不是单列 直接创建
createBean(beanName,beanDefinition);
}
}
}
// 创建
public Object createBean(String beanName,BeanDefinition beanDefinition){
Class clazz = beanDefinition.getClazz();
try {
Object instance = clazz.getConstructor().newInstance();
// DI注入 在创建实例的时候拿到所有的属性 判断属性上面有没有需要DI注入的 有的话就给他先实例化
for (Field declaredField : clazz.getDeclaredFields()) {
if (declaredField.isAnnotationPresent(Autowired.class)){
declaredField.setAccessible(true);
declaredField.set(instance,getBean(declaredField.getName()));
}
}
// 回调
if (instance instanceof BeanNameAware){
((BeanNameAware)instance).setBeanName(beanName);
}
// 前置
for (BeanPostProsessor beanPostProsessor : beanPostProsessorArrayList) {
instance = beanPostProsessor.Before(beanName,instance);
}
// 初始化
if (instance instanceof InitializingBean){
((InitializingBean)instance).afterPropertiesSet();
}
// 后置
for (BeanPostProsessor beanPostProsessor : beanPostProsessorArrayList) {
instance = beanPostProsessor.After(beanName,instance);
}
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
// 获取
public Object getBean(String beanName){
// 根据名字拿到定义信息
BeanDefinition beanDefinition = concurrentHashMap.get(beanName);
if (beanDefinition == null){
return new RuntimeException();
}else {
// 拿到Scope
String type = beanDefinition.getType();
// 如果是单例就创建并且放入单例池
if (type.equals("singleton")){
// 从单例池拿到bean
Object bean = singletonObjects.get(beanName);
if (bean == null){
Object o = createBean(beanName, beanDefinition);
singletonObjects.put(beanName,o);
}
return bean;
}else {
// 多例直接创建
return createBean(beanName, beanDefinition);
}
}
}
}
package com.project.service;
import com.project.spring.BeanPostProsessor;
import com.project.spring.Component;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
@Component
public class MyBeanPostProsessor implements BeanPostProsessor {
@Override
public Object Before(String beanName, Object bean) {
if (beanName.equals("userService")){
System.out.println("前置执行");
}
return bean;
}
@Override
public Object After(String beanName, Object bean) {
if (beanName.equals("userService")){
System.out.println("后置执行");
Object instance = Proxy.newProxyInstance(MyBeanPostProsessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("切面逻辑执行");
// 执行的是普通对象方法而不是代理对象
return method.invoke(method, args);
}
});
return instance;
}
return bean;
}
}