title: 暑假最后几天!肝爆(手写)一个Spring之Day3下午
date: 2022-08-15 23:26:59
categories:
- 手写spring
Day03下午—Spring 完成DI
思路
-
入口:getBean()方法
-
ApplicationContext中定义好IoC容器
-
BeanWrapper保存到Map中
-
所以设计两个Map
- factoryBeanObjectCache:保存单例对象的缓存
- factoryBeanInstanceCache:保存BeanWrapper的缓存
public class MyApplicationContext extends MyDefaultListableBeanFactory implements MyBeanFactory { ... //用来保证注册式单例的容器 private Map<String,Object> factoryBeanObjectCache = new HashMap<>(); //用来存储所有的被代理过的对象 private Map<String,MyBeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<>(); ...
完善getBean()
-
BeanPostProcessor:我们知道它是原生spring中为对象初始化事件设置的一种回调机制。暂时只做声明,没做具体实现。
package com.czh.spring.framework.beans.config; public class MyBeanPostProcessor { //TODO 为在Bean的初始化之前提供回调接口 public Object postProcessBeforeInitialization(Object bean,String beanName)throws Exception{ return bean; } //TODO 为在Bean的初始化之后提供回调接口 public Object postProcessAfterInitialization(Object bean,String beanName)throws Exception{ return bean; } }
-
在MyApplicationContext完善代码
-
大体流程
@Override public Object getBean(String beanName) throws Exception { MyBeanDefinition beanDefinition = super.beanDefinitionMap.get(beanName); //生成通知事件 MyBeanPostProcessor beanPostProcessor = new MyBeanPostProcessor(); Object instance = instantiateBean(beanDefinition); if(null == instance)return null; //在实例初始化以前调用一次 beanPostProcessor.postProcessBeforeInitialization(instance,beanName); MyBeanWrapper beanWrapper = new MyBeanWrapper(instance); this.factoryBeanInstanceCache.put(beanName,beanWrapper); //在是实例初始化以后再调用一次 beanPostProcessor.postProcessAfterInitialization(instance,beanName); populateBean(beanName,instance); return this.factoryBeanInstanceCache.get(beanName).getWrappedInstance(); }
-
instantiateBean方法:返回一个实例Bean
private Object instantiateBean(MyBeanDefinition beanDefinition) { Object instance = null; String beanClassName = beanDefinition.getBeanClassName(); try { //因为根据Class才能确定一个类是否有实例 if(this.factoryBeanObjectCache.containsKey(beanClassName)){ instance = this.factoryBeanObjectCache.get(beanClassName); }else { Class<?> clazz = Class.forName(beanClassName); instance = clazz.newInstance(); this.factoryBeanObjectCache.put(beanDefinition.getFactoryBeanName(),instance); } return instance; } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; }
-
populateBean方法
private void populateBean(String beanName, Object instance) { Class<?> clazz = instance.getClass(); if (!(clazz.isAnnotationPresent(MyController.class) || clazz.isAnnotationPresent(MyService.class))){ return; } Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if(!field.isAnnotationPresent(MyAutowired.class))continue; MyAutowired autowired = field.getAnnotation(MyAutowired.class); String autowiredBeanName = autowired.value().trim(); //没有指定beanName就采用默认类名作为beanName if("".equals(autowiredBeanName)){ autowiredBeanName = field.getType().getName(); } field.setAccessible(true); try { field.set(instance,this.factoryBeanInstanceCache.get(autowiredBeanName).getWrappedInstance()); } catch (IllegalAccessException e) { e.printStackTrace(); } } }