(一)手写Spring项目之IOC
项目地址:https://github.com/iamzhubaoliang/MySpring
1. 什么是IOC
IOC Inversion of Control 即控制反转,它可以降低代码之间的耦合性,最长见的就是Spring的依赖注入,它是怎么反转的?因为它的对象并不是我们new出来的而是被动的由容器进行注入的,spring相当于中间连接将原对象与属性进行了分离,由spring来控制对象的生命周期。
2. 实现方式
我们依旧是使用三级缓存
回顾一下Spring的三级缓存过程,顺便回顾一下循环依赖是怎么解决的
- 首先Spring会执行GetBean,GetBean为空壳方法,调用doGetBean
- 然后执行getSingleton(Beanname,true)方法从一级缓存中查找,然后判断是不是正在创建,此时A一定不存在所以为空,然后进入它的重载方法getsingleTon(Beannaem,singletonFactory)方法,singletonFactory为一个lambda表达式,其为函数式接口的实现。
- 然后进入singleton方法中,执行lanbda表达式getObject(在接口ObjectFactory中),这个getObject方法中是我们传进来的实现createBean,里面只有doCreateBean方法,执行DoCreatBean,然·后执行CrateBeanInstance方法,这个时候就会创建A的实例化对象,但这个是原始的对象,没有进行属性填充的,所以在doCreateBean中同时进行属性的填充。
- 在向A中填充B之前有一个向三级缓存中添加一个键值对的过程,添加了beanName和getEarlyBeanRefrence(beanname,bean)(将A传入了这个lamda表达式中),然后向A里填充B,发现B没有
- 执行this.Factory.getBean()查找B,B找不到,然后再执行A的那一套,将B的name和getEarlyRefrence lambda表达式扔到三级缓存,最终到了填充B的A属性的时候,getBean,doGetBean后,执行getsingleton发现缓存中有A,所以从三级缓存中删除键值对,放到二级缓存,此时进行填充,填充成功后执行addsingleton B放入一级缓存删掉三级缓存B键值对
- 上面这些过程都是在创建A时候的调用,所以层层返回填充A,执行addsingleton ,执行删掉二级缓存中A,放入一级缓存,
- 因为创建是一个循环,所以程序会继续执行,getBean,拿B这一次从一级缓存中直接拿到了B,到此结束
- 其中那个getEarlyBeanRefrence表达式是用来解决aop的,当从三级缓存拿对象的时候,如果不是则直接返回原始对象,如果有动态代理则返回一个代理对象,这样就实现了aop
我们来分析一下三级缓存的作用,一级缓存singletonobjects是存放已经注入的对象,earlysingletonObjects是存放半成品也就是没有进行属性注入的Bean,此时的Bean虽然是半成品却可以被其他对象所引用,第三级缓存是用来创建代理对象的,我们放入三级缓存的并不是我们原始用反射创建的Bean,而是一个动态的工厂,当我们从工厂中取对象的时候如果发现有通知(增强)那么取的就是代理对象,如果不是直接返回原始对象
3. 手动实现的方式
IOC最重要的就是属性的注入了
手写的思路
- 创建Autowired,创建CompoentScan,Compoentd等注解
- 创建三级缓存
- 实现Bean的生命周期:Bean的生命周期如下
1)实例化Bean
2)如果Bean实现了BeanNameAware接口就执行setBeanName方法
3)如果Bean实现了ApplicationContextAware接口就执行setApplicationContext方法
4)如果Bean实现了BeanPostProcessor接口就执行postProcessBeforeInitialization
5)如果Bean 实现了InitializingBean接口,执行afterPropertiesSet()方法
6)如果bean使用init-method声明了初始化方法,则执行初始化方法
7)如果Bean实现了BeanPostProcessor接口就执行postProcessAfterInitialization
8)如果bean实现了DisposableBean接口,则执行destory()方法
上述只是简单的生命周期,中间还有其他的复杂过程参考https://zhuanlan.zhihu.com/p/344140024 - 我们使用spring的时候一般是getBean,而具体创建的时候就是CreateBean,创建完成后属性注入,成品放入一级缓存
代码
1.扫描:
- 首先要根据ComponentScan获取扫描路径,接着递归扫描目录,将所有带有Component注解的类用一个BeanDefintion(用来描述Bean)包装的类包装然后放入beanDefintionHashMap,这个map用来存储扫描过程中的Bean的描述
- 判断此类是否实现了BeanPostProcessor接口,如果实现了就要实例化这个class放入BeanPostProcessorList,这个list用来存放所有的后置处理器
- 如果是Controller同时将描述的Controller属性置true
- 然后获取Scope属性将Scope的值放入BeanDefintion
- 最后放入map中
这样就将所有的Bean完成了扫描
public static void LoadAllBean() {
for (Class<?> clazz : classesHashSet) {
if (!(clazz.isAnnotationPresent(Component.class)||clazz.isAnnotationPresent(Controller.class)))
continue;
BeanDefintion newBeanDefine = new BeanDefintion();
newBeanDefine.setClazz(clazz);
String BeanName=clazz.getName();
BeanName=getBeanName(BeanName);
if(clazz.isAnnotationPresent(Component.class)&&!clazz.getAnnotation(Component.class).value().equals(""))
BeanName=clazz.getAnnotation(Component.class).value();
if(clazz.isAnnotationPresent(Controller.class)&&!clazz.getAnnotation(Controller.class).value().equals("")) {
BeanName = clazz.getAnnotation(Controller.class).value();
}
if(clazz.isAnnotationPresent(Controller.class))
newBeanDefine.setIsController(true);
newBeanDefine.setBeanName(BeanName);
//加载后置处理器
if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
try {
BeanPostProcessorList.add((BeanPostProcessor) clazz.getDeclaredConstructor().newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
//scope
if (clazz.isAnnotationPresent(Scope.class)) {
String scope = clazz.getDeclaredAnnotation(Scope.class).value();
newBeanDefine.setScope(scope);
} else {
//默认为单例模式
newBeanDefine.setScope(ScopeEnum.SingleTon.toString());
}
//添加切面
if (clazz.isAnnotationPresent(Aspect.class)) {
for (Method method : clazz.getMethods()) {
String annotationPath = "";
if (method.isAnnotationPresent(PointCut.class)) {
String delegateString = method.getAnnotation(PointCut.class).value();
annotationPath=delegateString;
if (delegateString.charAt(delegateString.length() - 1) == ')') {
//说明是在某个方法上面的切面
annotationPath =annotationPath.replace("()","");
//切掉方法保留到类
String[] seg=cutName(annotationPath);
AddToAspects(clazz,seg[0],true,seg[1]);
}else
{//切面是某个包或者类
String annotationPathClone=new String(annotationPath);
URL resource=Container.classLoader.getResource(annotationPathClone.replace(".","/"));
if(resource==null)
resource=Container.classLoader.getResource(annotationPathClone.replace(".","/")+".class");
File file=new File(resource.getFile());
// System.out.println(file);
if(file.isDirectory()) {
ArrayList<File> fileArray=new ArrayList<>();
DFSgetCureentDir(file,fileArray);
for(File f:fileArray)
{
String key= f.getAbsolutePath().replace("\\",".");
key=key.substring(key.indexOf(annotationPath),key.indexOf(f.getName())+f.getName().length()-6);
AddToAspects(clazz,key,false,"");
}
}else
{
String key= file.getAbsolutePath().replace("\\",".");
key=key.substring(key.indexOf(annotationPath),key.indexOf(file.getName())+file.getName().length()-6);
AddToAspects(clazz,key,false,"");
}
}
}
}
}
beanDefintionHashMap.put(newBeanDefine.getBeanName(), newBeanDefine);
}
}
AddToAspects是用来添加通知的先不用管,这个后期做AOP的时候讲解
2.创建
创建过程就是对象在三级缓存中移动,在真实的Spring中利用一个getEarlyBeanRefrence(beanname,bean)的lambda表达式来获取代理或者原始对象这里使用的是一个动态工厂来获取,其实原理是一样的,lambda表达式就是一个函数调用,它是一个函数式接口,有关函数式接口的资料自行查阅
这一部分是IOC的核心部分,会有点多,但基本原理开始已经阐述了,其实很简单,代码虽然多单实现的路基很简单
- 上面创建了Bean的描述,这里就要按照描述来创建Bean了,ProductBean()用来遍历beanDefintionHashMap并调用CreateBean函数
- CreateBean的逻辑就是开始讲述的IOC三级缓存了。
其他相关描述见注释
public static void ProductBean()
{
for (String beanName : beanDefintionHashMap.keySet()) {
BeanDefintion beanDefintion = beanDefintionHashMap.get(beanName);
// 如果是单例就Create,因为如果不是Singleton单例每次拿的时候是先创建并不是从缓存中拿取
if (beanDefintion.getScope().equals(ScopeEnum.SingleTon.toString())) {
CreateBean(beanDefintion,true);
}
}
}
private static Object CreateBean(BeanDefintion beanDefintion,Boolean sinleton) {
//判断是不是在二级缓存中存在
try {
//如果在一级直接返回
if(Container.singletonObjects.containsKey(beanDefintion.getBeanName())&&sinleton)
return Container.singletonObjects.get(beanDefintion);
else if(Container.earlySingletonObjects.containsKey(beanDefintion.getBeanName()))
{
//这里返回引用,是半成品,为了填充依赖于它的对象
return Container.earlySingletonObjects.get(beanDefintion.getBeanName());
}else {
if(beanDefintion.getClazz().isInterface())
return null;
//调用后置处理器
//调用后置处理器方法
Object instance = beanDefintion.getClazz().getDeclaredConstructor().newInstance();
DynamicBeanFactory dynamicBeanFactory = new DynamicBeanFactory();
dynamicBeanFactory.setInstance(instance);
dynamicBeanFactory.setBeanDefintion(beanDefintion);
//查看是否存在切面并放入工厂中,在工厂中准备代理
if(BeforeDelegatedSet.containsKey(beanDefintion.getClazz().getName()))
{
dynamicBeanFactory.setDelegated(true);
dynamicBeanFactory.setBeforemethodCache(BeforeDelegatedSet.get(beanDefintion.getClazz().getName()));
}
if(AfterDelegatedSet.containsKey(beanDefintion.getClazz().getName()))
{
dynamicBeanFactory.setDelegated(true);
dynamicBeanFactory.setAftermethodCache(AfterDelegatedSet.get(beanDefintion.getClazz().getName()));
}
//扔到三级缓存
Container.singletonFactory.put(beanDefintion.getBeanName(), dynamicBeanFactory);
populate(beanDefintion.getBeanName());
//扔到二级
Container.earlySingletonObjects.put(beanDefintion.getBeanName(),Container.singletonFactory.get(beanDefintion.getBeanName()).getTarget());
Container.singletonFactory.remove(beanDefintion.getBeanName());
//扔到一级
Container.singletonObjects.put(beanDefintion.getBeanName(),Container.earlySingletonObjects.get(beanDefintion.getBeanName()));
//后置处理器
Container.earlySingletonObjects.remove(beanDefintion.getBeanName());
//加入Controllermap引用
if(beanDefintion.isController())
Container.controllerMap.put(beanDefintion.getBeanName(),Container.singletonObjects.get(beanDefintion.getBeanName()));
//如果实现了BeanNameAware接口就调用SetBeanName设置BeanName
if(instance instanceof BeanNameAware)
{
((BeanNameAware)instance).SetBeanName(beanDefintion.getBeanName());
}
for(BeanPostProcessor processor:BeanPostProcessorList)
{
Container.singletonObjects.put(beanDefintion.getBeanName(),processor.postProcessBeforeInitialization(instance,beanDefintion.getBeanName()));
}
//如果实现了InitializingBean接口就调用afterPropertiesSet
if(instance instanceof InitializingBean)
{
((InitializingBean) instance).afterPropertiesSet();
}
for(BeanPostProcessor processor:BeanPostProcessorList)
{
Container.singletonObjects.put(beanDefintion.getBeanName(),processor.postProcessAfterInitialization(instance,beanDefintion.getBeanName()));
}
}
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
if(!sinleton)
{
Object obj=Container.singletonObjects.get(beanDefintion.getBeanName());
//因为创建完成后最后都放入一级缓存,如果不是单例就要删除
Container.singletonObjects.remove(beanDefintion.getBeanName());
return obj;
}
return null;
}
/**
* 获取属性,填充属性
*/
private static void populate(String BeanName)
{
try {
Class<?> bean=Container.singletonFactory.get(BeanName).getBeanDefintion().getClazz();
//获取所有的变量,看看有没有Autowired注解,调用getBean取所注入的Bean
for (Field delclaredField : bean.getDeclaredFields())
{
if(!delclaredField.isAnnotationPresent(Autowired.class))
continue;
String[] name=delclaredField.getType().toString().split("\\.");
String benName=name[name.length-1];
String a=delclaredField.getAnnotation(Autowired.class).value();
if(!delclaredField.getAnnotation(Autowired.class).value().equals(""))
benName=delclaredField.getAnnotation(Autowired.class).value();
Object fBean = getBean(benName);
delclaredField.setAccessible(true);
delclaredField.set(Container.singletonFactory.get(BeanName).getInstance(), fBean);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public static Object getBean(String BeanName)
{//没有判断是不是单例,后期改进
if(beanDefintionHashMap.get(BeanName).getScope().equals(ScopeEnum.SingleTon))
{
//有直接从一级缓存中拿到成品
if (Container.singletonObjects.containsKey(BeanName))
return Container.singletonObjects.get(BeanName);
else {
return CreateBean(beanDefintionHashMap.get(BeanName),true);
}
}else
{ 没有就调用CreateBean创建
return CreateBean(beanDefintionHashMap.get(BeanName),false);
}
}