简介
接上文,从serlvet到applicationContext。
- 从v1.0.1servlet到applicationContext,做了如下调整:
- 1.将ioc和di的功能放到了applicationContext
- 2.增加了控制层方法参数的数据类型转换
- 3.增加了控制层@MyRequestParam注解的required属性
- 4.增加了懒加载注解
主要类如下:ApplicationContext 、BeanDefinitionReader、BeanDefinition、BeanWrapper、DefaultListableFactory
流程如下:DispatcherServlet通过ApplicationContext进行ioc和di过程,ApplicationContext 通过BeanDefinitionReader进行配置文件的读取,并解析成BeanDefinition,随后将BeanDefinition缓存到DefaultListableFactory,随后进行实例化。
实例化过程如下:根据beanName获取BeanDefinition,反射实例化Bean,封装成Beanwrapper,进行依赖注入,存入ioc。
di过程主要通过三级缓存解决了循环依赖的问题。
IoC
BeanDefinition Bean配置信息
public class MyBeanDefinition {
/**
* 类的beanName
**/
private String factoryBeanName;
/**
* 类的全限定名
**/
private String beanClassName;
/**
* 类是否懒加载
**/
private boolean lazyInit = false;
public MyBeanDefinition(String factoryBeanName, String beanClassName, boolean lazyInit) {
this.factoryBeanName = factoryBeanName;
this.beanClassName = beanClassName;
this.lazyInit = lazyInit;
}
public MyBeanDefinition(String factoryBeanName, String beanClassName) {
this.factoryBeanName = factoryBeanName;
this.beanClassName = beanClassName;
}
public String getFactoryBeanName() {
return factoryBeanName;
}
public String getBeanClassName() {
return beanClassName;
}
public boolean isLazyInit() {
return lazyInit;
}
}
BeanWrapper Bean的包装类
public class MyBeanWrapper {
/**
* 类实例
**/
private Object wrappedInstance;
/**
* 类对象
**/
private Class<?> wrappedClazz;
public Object getWrappedInstance() {
return wrappedInstance;
}
public Class<?> getWrappedClazz() {
return wrappedClazz;
}
public MyBeanWrapper(Object wrappedInstance, Class wrappedClazz) {
this.wrappedInstance = wrappedInstance;
this.wrappedClazz = wrappedClazz;
}
}
BeanDefinitionReader BeanDefinition的读取与解析工具
public class MyBeanDefinitionReader {
/**
* 保存的配置文件
**/
private Properties contextConfig = new Properties();
/**
* 配置文件分隔符
**/
private static final String SPLITSYMBOL = ";";
/**
* 待注册到ioc的class
**/
private List<String> registerBeanClasses = new ArrayList<String>();
public MyBeanDefinitionReader(String configs){
//web.xml中获取配置文件路径后加载文件
for (int i = 0; i < configs.split(SPLITSYMBOL).length; i++) {
contextConfig.remove("scanPackage");
doLoadConfig(configs.split(SPLITSYMBOL)[i]);
//配置文件中获取属性后扫包
doScan(contextConfig.getProperty("scanPackage"));
}
}
/**
* 解析配置文件,将所有需要注册成bean的class创建BeanDefinition=====可能存在相同beanName
*
* @param
* @return java.util.List<com.yjf.spring.mvcframework.v2.ioc.beans.config.MyBeanDefinition>
**/
public List<MyBeanDefinition> loadBeanDefinitions(){
if (registerBeanClasses.isEmpty()) {
return new ArrayList<>();
}
List<MyBeanDefinition> result = new ArrayList<>();
for (String registerBeanClass : registerBeanClasses) {
try{
Class<?> clazz = Class.forName(registerBeanClass);
//若为接口,则跳过
if(clazz.isInterface()){
continue;
}
if (clazz.isAnnotationPresent(MyController.class) || clazz.isAnnotationPresent(MyService.class)) {
//默认beanName : 类名首字母小写
String beanName = StringUtil.firstCaseToLower(clazz.getSimpleName());
//自定义beanName
String defineBeanName = clazz.getAnnotation(MyService.class) == null ? clazz.getAnnotation(MyController.class).value() : clazz.getAnnotation(MyService.class).value();
//若为空,则使用默认beanName
if (!StringUtil.isEmpty(defineBeanName)) {
beanName = defineBeanName;
}
//是否懒加载
MyLazy myLazy = clazz.getAnnotation(MyLazy.class);
if(null != myLazy && myLazy.value() == true){
result.add(new MyBeanDefinition(beanName,registerBeanClass,true));
}else {
result.add(new MyBeanDefinition(beanName,registerBeanClass));
}
}else {
continue;
}
}catch (Exception e){
e.printStackTrace();
}
}
return result;
}
/**
* 将包路径转成文件路径,扫描文件夹,存下文件后缀名为class的全限定名
*
* @param scanPackage 包名
* @return void
**/
private void doScan(String scanPackage) {
String fileSuffix = scanPackage.replaceAll("\\.", "/");
File root = new File(this.getClass().getClassLoader().getResource("").getPath(), fileSuffix);
for (File file : root.listFiles()) {
if (file.isDirectory()) {
doScan(scanPackage + "." + file.getName());
} else {
if (!file.getName().endsWith(".class")) {
continue;
}
registerBeanClasses.add(scanPackage + "." + file.getName().replace(".class", ""));
}
}
}
/**
* 通过Properties加载配置文件
*
* @param contextConfigLocation 配置文件路径
* @return void
**/
private void doLoadConfig(String contextConfigLocation) {
InputStream is = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
try {
contextConfig.load(is);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
BeanFactory 定义接口
public interface MyBeanFactory {
Object getBean(String beanName);
/**
* 通过类的全限定名获取bean
*
* @param clazz
* @return java.lang.Object
**/
Object getBean(Class clazz);
}
DefaultListableBeanFactory 缓存待注册的BeanDefinition
public class MyDefaultListableBeanFactory implements MyBeanFactory {
public Map<String, MyBeanDefinition> beanDefinitionMap = new HashMap<>();
@Override
public Object getBean(String beanName) {
return null;
}
@Override
public Object getBean(Class clazz) {
return null;
}
/**
* 缓存配置文件,检测是否存在相同beanName
*
* @param beanDefinitions
* @return void
**/
public void doRegisterBeanDefinition(List<MyBeanDefinition> beanDefinitions){
for (MyBeanDefinition beanDefinition : beanDefinitions) {
//存在同名类却未起别名
if(beanDefinitionMap.containsKey(beanDefinition.getFactoryBeanName())){
throw new Error("The " + beanDefinition.getFactoryBeanName() + " already exists,please use alias!");
}
beanDefinitionMap.put(beanDefinition.getFactoryBeanName(),beanDefinition);
}
}
}
DispatcherServlet
public class MyDispatcherServlet extends HttpServlet {
private MyApplicationContext myApplicationContext = null;
/**
* 键 : 请求url , 值 : 请求url对应的方法
**/
private Map<String, Method> handlerMapping = new HashMap<String, Method>();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
dispatcher(req, resp);
} catch (Exception e) {
e.printStackTrace();
resp.getWriter().write("500 Exception,Detail : " + Arrays.toString(e.getStackTrace()));
}
}
/**
* 运行阶段,根据url委派给具体的method
* <p>
* 1. 根据url取出method
* 2. 参数赋值
* 3. 反射调用方法
* 4. 响应浏览器
**/
private void dispatcher(HttpServletRequest req, HttpServletResponse resp) throws IOException, InvocationTargetException, IllegalAccessException {
//去除上下文
String uri = req.getRequestURI().replace(req.getContextPath(),"").replaceAll("/+","/");
if(!handlerMapping.containsKey(uri)){
resp.getWriter().write("404 page not found!");
return;
}
//取出方法
Method method = handlerMapping.get(uri);
//形参数组
Parameter[] parameters = method.getParameters();
//必须形参位置
int[] indexes = new int[parameters.length];
Arrays.fill(indexes,-1);
//实参数组
Object[] args = new Object[parameters.length];
//控制层对象
String defineBeanName = method.getDeclaringClass().getAnnotation(MyController.class).value();
Object instance = StringUtil.isEmpty(defineBeanName) ? myApplicationContext.getBean(StringUtil.firstCaseToLower(method.getDeclaringClass().getSimpleName())) : myApplicationContext.getBean(defineBeanName);
//形参名-->形参位置
Map<String,Integer> paramIndexMapping = new HashMap<>(3);
//先将形参名和形参位置建立联系,而后通过实参名获取实参名位置
for (int i = 0; i < parameters.length; i++) {
//获取参数注解
// Annotation[] parameterAnnotation = parameters[i].getAnnotations();
//获取@MyRequestParam注解的值,若值存在,则paramIndexMapping中键为该值,若不存在,则paramIndexMapping中键为形参参数名
MyRequestParam param = parameters[i].getAnnotation(MyRequestParam.class);
if(null == param || StringUtil.isEmpty(param.value())){
paramIndexMapping.put(parameters[i].getName(),i);
}else {
paramIndexMapping.put(param.value(),i);
if(param.required() == true) {
indexes[i] = 1;
}
}
//注入HttpServletRequest和HttpServletResponse
if(parameters[i].getType() == HttpServletRequest.class){
args[i] = req;
}
if(parameters[i].getType() == HttpServletResponse.class){
args[i] = resp;
}
}
//获取实参
Enumeration<String> parameterNames = req.getParameterNames();
while(parameterNames.hasMoreElements()){
//实参参数名
String paramKey = parameterNames.nextElement();
//参数名对应的位置
Integer integer = paramIndexMapping.get(paramKey);
if (null != integer) {
if (parameters[integer].getType().isArray()) {
args[integer] = convert(parameters[integer], req.getParameterValues(paramKey));
} else {
args[integer] = convert(parameters[integer], req.getParameter(paramKey));
}
}
}
//判断必须参数在实参中是否存在
for (int i = 0; i < indexes.length; i++) {
int index = indexes[i];
if(index == 1 && args[i] == null){
throw new Error(parameters[i].getName() + " is required!");
}
}
Object result = method.invoke(instance, args);
resp.getWriter().write(String.valueOf(result));
}
/**
* 转换实参值的数据类型
*
* @param param 形参
* @param value 实参值
* @return java.lang.Object 转换后的实参
**/
private Object convert(Parameter param, String... value) {
if (value == null || value.length == 0) {
return null;
}
//单值
if (value.length == 1) {
Class<?> type = param.getType();
IConvertStrategy convertStrategy = ConvertStrategyFactory.getConvertStrategy(type.getSimpleName());
return convertStrategy.convertString(value[0]);
//数组
} else {
Class<?> componentType = param.getType().getComponentType();
IConvertStrategy convertStrategy = ConvertStrategyFactory.getConvertStrategy(componentType.getSimpleName());
Object result = Array.newInstance(componentType, value.length);
for (int i = 0; i < value.length; i++) {
Array.set(result,i,convertStrategy.convertString(value[i]));
}
return result;
}
}
@Override
/**
* spring初始化过程
*
* 1. 传入配置文件地址,上下文完成解析配置文件,ioc与di
* 2. mvc,迭代ioc,将url和method进行映射 存储到handlerMapping : Map
*
* @param config
* @return void
**/
public void init(ServletConfig config) throws ServletException {
myApplicationContext = new MyApplicationContext(config.getInitParameter("contextConfigLocation"));
//将url和method进行映射
doInitHandlerMapping();
System.out.println("init finish");
}
/**
* 将url和method进行映射,迭代ioc,控制层存在@RequestMapping注解的公有方法需要进行映射
*
* @param
* @return void
**/
private void doInitHandlerMapping() {
if (myApplicationContext.getBeanDefinitionCount() == 0) {
return;
}
for (String beanName : myApplicationContext.getBeanDefinitionNames()) {
if(myApplicationContext.getBeanDefinitionByName(beanName).isLazyInit()){continue;}
Object instance = myApplicationContext.getBean(beanName);
Class<?> clazz = instance.getClass();
if(!clazz.isAnnotationPresent(MyController.class)){
continue;
}
String baseUrl = clazz.getAnnotation(MyRequestMapping.class) != null ? clazz.getAnnotation(MyRequestMapping.class).value() : "";
//遍历控制层下所有公有方法
for (Method method : clazz.getMethods()) {
if(!method.isAnnotationPresent(MyRequestMapping.class)){
continue;
}
String pattern = "/" + baseUrl + "/" + method.getAnnotation(MyRequestMapping.class).value();
String url = pattern.replaceAll("/+","/");
if(handlerMapping.containsKey(url)){
throw new RuntimeException(url + " already exists,mapping exception!");
}
handlerMapping.put(url,method);
System.out.println(String.format("Mapped %s--->%s",url,method));
}
}
}
}
ApplicationContext
public class MyApplicationContext implements MyBeanFactory {
private MyBeanDefinitionReader myBeanDefinitionReader;
private MyDefaultListableBeanFactory myDefaultListableBeanFactory = new MyDefaultListableBeanFactory();
/**
* ioc容器
**/
private Map<String, MyBeanWrapper> factoryBeanInstanceCache = new HashMap<>();
/**
* 三级缓存====AOP
**/
private Map<String, Object> factoryBeanObjectCache = new HashMap<>();
public MyApplicationContext(String configs) {
//加载配置文件到工具类
myBeanDefinitionReader = new MyBeanDefinitionReader(configs);
//工具类解析配置文件返回配置信息
List<MyBeanDefinition> myBeanDefinitions = myBeanDefinitionReader.loadBeanDefinitions();
//缓存配置信息到工厂
myDefaultListableBeanFactory.doRegisterBeanDefinition(myBeanDefinitions);
//加载非懒加载bean
doInstance();
}
private void doInstance() {
//获取待注册bean
Map<String, MyBeanDefinition> beanDefinitionMap = this.myDefaultListableBeanFactory.beanDefinitionMap;
for (Map.Entry<String, MyBeanDefinition> stringMyBeanDefinitionEntry : beanDefinitionMap.entrySet()) {
String beanName = stringMyBeanDefinitionEntry.getKey();
if (!stringMyBeanDefinitionEntry.getValue().isLazyInit()) {
getBean(beanName);
}
}
}
@Override
public Object getBean(String beanName) {
Map<String, MyBeanDefinition> beanDefinitionMap = this.myDefaultListableBeanFactory.beanDefinitionMap;
//获取beanDefinition
MyBeanDefinition myBeanDefinition = beanDefinitionMap.get(beanName);
if(this.factoryBeanInstanceCache.containsKey(beanName)){
return this.factoryBeanInstanceCache.get(beanName).getWrappedInstance();
}
//反射实例化
Object instance = instantiateBean(beanName, myBeanDefinition);
//包装Bean
MyBeanWrapper myBeanWrapper = new MyBeanWrapper(instance, instance.getClass());
//依赖注入
populateBean(myBeanWrapper);
//保存到ioc容器中
this.factoryBeanInstanceCache.put(beanName, myBeanWrapper);
//将当前类的全限定名和类实例存入ioc
this.factoryBeanInstanceCache.put(myBeanDefinition.getBeanClassName(), myBeanWrapper);
//将当前类实现的接口注册到ioc,键:接口全限定名 值: 当前类对象;存在多个实现类的时候移除注册
try {
for (Class<?> clazzInterface : Class.forName(myBeanDefinition.getBeanClassName()).getInterfaces()) {
if (factoryBeanInstanceCache.containsKey(clazzInterface.getName())) {
this.factoryBeanInstanceCache.remove(clazzInterface.getName());
}else {
this.factoryBeanInstanceCache.put(clazzInterface.getName(), myBeanWrapper);
}
}
}catch (Exception e){
e.printStackTrace();
}
return myBeanWrapper.getWrappedInstance();
}
private void populateBean(MyBeanWrapper myBeanWrapper) {
Object wrappedInstance = myBeanWrapper.getWrappedInstance();
Class<?> wrappedClazz = myBeanWrapper.getWrappedClazz();
//获取类对象下所有字段,根据是否存在注解@MyAutowired决定是否进行依赖注入
for (Field field : wrappedClazz.getDeclaredFields()) {
if (!field.isAnnotationPresent(MyAutowired.class)) {
continue;
}
//自定义beanName
String defineBeanName = field.getAnnotation(MyAutowired.class).value();
//默认以字段类型首字母小写作为beanName
String beanName = StringUtil.firstCaseToLower(field.getType().getSimpleName());
//类全限定名作为beanName
String fullBeanName = field.getType().getName();
//暂存默认beanName
String simpleBeanName = beanName;
//标志defineBeanName是否为空
boolean flag = true;
if (!StringUtil.isEmpty(defineBeanName)) {
beanName = defineBeanName;
flag = false;
}
if (!flag) {
if (null == factoryBeanInstanceCache.get(beanName)) {
beanName = simpleBeanName;
}
}
if (null == factoryBeanInstanceCache.get(beanName)) {
beanName = fullBeanName;
}
ReflectUtil.fieldSetting(field, wrappedInstance, factoryBeanInstanceCache.get(beanName) == null ? null : factoryBeanInstanceCache.get(beanName).getWrappedInstance());
}
}
private Object instantiateBean(String beanName, MyBeanDefinition myBeanDefinition) {
try {
Class<?> clazz = Class.forName(myBeanDefinition.getBeanClassName());
Object instance = clazz.newInstance();
//如果是代理对象,触发AOP的逻辑
this.factoryBeanObjectCache.put(beanName, instance);
return instance;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public Object getBean(Class clazz) {
return getBean(clazz.getName());
}
public int getBeanDefinitionCount(){
return this.myDefaultListableBeanFactory.beanDefinitionMap.size();
}
public String[] getBeanDefinitionNames(){
return this.myDefaultListableBeanFactory.beanDefinitionMap.keySet().toArray(new String[]{});
}
public MyBeanDefinition getBeanDefinitionByName(String beanName){
return this.myDefaultListableBeanFactory.beanDefinitionMap.get(beanName);
}
}
DI
循环依赖:多个类之间形成依赖闭环。eg: A{B b} B{A a}
跟手写spring1.0不同,1.0中是所有类先进行实例化存入ioc,再进行DI,因此不会出现循环依赖问题。而2.0中是一边实例化一边di,因此会出现di时其他类还未创建的情况。
当只存在一级缓存时,由于类A还在进行依赖注入,并没有存入一级缓存,所以当B注入A时无法完成,形成依赖死循环。
就解决循环依赖而言,两级缓存就可以解决,可能考虑到功能扩展及aop的其它问题,spring中使用了三级缓存。
构造器注入循环依赖无法解决。
public A{
public A(){
new B();
}
}
public B{
public B(){
new A();
}
}
解决循环依赖的关键在于类A实例化后di之前的对象应该保留曝光出来,使得类B可以注入A。
而构造器循环依赖无法实例化任何一个对象,形成依赖死循环。
非单例循环依赖无法解决。
三级缓存存的都是单例对象。
BeanDefinition
public class MyBeanDefinition {
/**
* 类的beanName
**/
private String factoryBeanName;
/**
* 类的全限定名
**/
private String beanClassName;
/**
* 类是否懒加载
**/
private boolean lazyInit = false;
public MyBeanDefinition(String factoryBeanName, String beanClassName, boolean lazyInit) {
this.factoryBeanName = factoryBeanName;
this.beanClassName = beanClassName;
this.lazyInit = lazyInit;
}
public MyBeanDefinition(String factoryBeanName, String beanClassName) {
this.factoryBeanName = factoryBeanName;
this.beanClassName = beanClassName;
}
public String getFactoryBeanName() {
return factoryBeanName;
}
public String getBeanClassName() {
return beanClassName;
}
public boolean isLazyInit() {
return lazyInit;
}
public boolean isSingleton(){
return true;
}
}
BeanDefinitionReader
public class MyBeanDefinitionReader {
/**
* 保存的配置文件
**/
private Properties contextConfig = new Properties();
/**
* 配置文件分隔符
**/
private static final String SPLITSYMBOL = ";";
/**
* 待注册到ioc的class
**/
private List<String> registerBeanClasses = new ArrayList<String>();
public MyBeanDefinitionReader(String configs) {
//web.xml中获取配置文件路径后加载文件
for (int i = 0; i < configs.split(SPLITSYMBOL).length; i++) {
contextConfig.remove("scanPackage");
doLoadConfig(configs.split(SPLITSYMBOL)[i]);
//配置文件中获取属性后扫包
doScan(contextConfig.getProperty("scanPackage"));
}
}
/**
* 解析配置文件,将所有需要注册成bean的class创建BeanDefinition=====可能存在相同beanName
*
* @param
* @return java.util.List<com.yjf.spring.mvcframework.v2.ioc.beans.config.MyBeanDefinition>
**/
public List<MyBeanDefinition> loadBeanDefinitions() {
if (registerBeanClasses.isEmpty()) {
return new ArrayList<>();
}
List<MyBeanDefinition> result = new ArrayList<>();
for (String registerBeanClass : registerBeanClasses) {
try {
Class<?> clazz = Class.forName(registerBeanClass);
//若为接口,则跳过
if (clazz.isInterface()) {
continue;
}
if (clazz.isAnnotationPresent(MyController.class) || clazz.isAnnotationPresent(MyService.class)) {
//默认beanName : 类名首字母小写
String beanName = StringUtil.firstCaseToLower(clazz.getSimpleName());
//自定义beanName
String defineBeanName = clazz.getAnnotation(MyService.class) == null ? clazz.getAnnotation(MyController.class).value() : clazz.getAnnotation(MyService.class).value();
//若为空,则使用默认beanName
if (!StringUtil.isEmpty(defineBeanName)) {
beanName = defineBeanName;
}
//是否懒加载
MyLazy myLazy = clazz.getAnnotation(MyLazy.class);
if (null != myLazy && myLazy.value() == true) {
for (Class<?> clazzInterface : clazz.getInterfaces()) {
result.add(new MyBeanDefinition(clazzInterface.getName(), registerBeanClass,true));
}
result.add(new MyBeanDefinition(beanName, registerBeanClass, true));
} else {
result.add(new MyBeanDefinition(beanName, registerBeanClass));
for (Class<?> clazzInterface : clazz.getInterfaces()) {
result.add(new MyBeanDefinition(clazzInterface.getName(), registerBeanClass));
}
}
} else {
continue;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
/**
* 将包路径转成文件路径,扫描文件夹,存下文件后缀名为class的全限定名
*
* @param scanPackage 包名
* @return void
**/
private void doScan(String scanPackage) {
String fileSuffix = scanPackage.replaceAll("\\.", "/");
File root = new File(this.getClass().getClassLoader().getResource("").getPath(), fileSuffix);
for (File file : root.listFiles()) {
if (file.isDirectory()) {
doScan(scanPackage + "." + file.getName());
} else {
if (!file.getName().endsWith(".class")) {
continue;
}
registerBeanClasses.add(scanPackage + "." + file.getName().replace(".class", ""));
}
}
}
/**
* 通过Properties加载配置文件
*
* @param contextConfigLocation 配置文件路径
* @return void
**/
private void doLoadConfig(String contextConfigLocation) {
InputStream is = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
try {
contextConfig.load(is);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
ApplicationContext
/** 循环依赖:存在依赖闭环
- eg: A{B b} B{A a}
- getBean(A) -> A实例化(标记创建中) (三级缓存持有该对象) ->注入B-> getBean(B) -> 实例化B(标记创建中)(三级缓存持有该对象) -> 注入A -> getBean(A) -> 三级缓存取得对象 -> B初始化完成(取消标记) -> 存入一级缓存 -> A初始化完成 (取消标记) -> 存入一级缓存
*/
public class MyApplicationContext implements MyBeanFactory {
private MyBeanDefinitionReader myBeanDefinitionReader;
private MyDefaultListableBeanFactory registry = new MyDefaultListableBeanFactory();
/**
* ioc容器
**/
private Map<String, MyBeanWrapper> factoryBeanInstanceCache = new HashMap<>();
/**
* 正在创建中的对象beanName
* 执行创建对象流程但还未初始化完成的bean带有该标记
* 不存在循环依赖的类创建对象时直接就放入一级缓存了,因此一级缓存中没有的bean且该bean存在标记时代表该类为循环依赖类
**/
private Set<String> singletonCurrentlyInCreation = new HashSet<>();
/**
* 一级缓存====保存初始化完成的bean
**/
private Map<String, Object> singletonObject = new HashMap<>();
/**
* 二级缓存====保存已创建对象但还未注入属性的bean,该容器存的都是循环依赖对象
**/
private Map<String, Object> earlySingletonObject = new HashMap<>();
/**
* 三级缓存====AOP
**/
private Map<String, Object> factoryBeanObjectCache = new HashMap<>();
public MyApplicationContext(String configs) {
//加载配置文件到工具类
myBeanDefinitionReader = new MyBeanDefinitionReader(configs);
//工具类解析配置文件返回配置信息
List<MyBeanDefinition> myBeanDefinitions = myBeanDefinitionReader.loadBeanDefinitions();
//缓存配置信息到工厂
registry.doRegisterBeanDefinition(myBeanDefinitions);
//加载非懒加载bean
doInstance();
}
private void doInstance() {
//获取待注册bean
Map<String, MyBeanDefinition> beanDefinitionMap = this.registry.beanDefinitionMap;
for (Map.Entry<String, MyBeanDefinition> stringMyBeanDefinitionEntry : beanDefinitionMap.entrySet()) {
String beanName = stringMyBeanDefinitionEntry.getKey();
if (!stringMyBeanDefinitionEntry.getValue().isLazyInit()) {
getBean(beanName);
}
}
}
@Override
public Object getBean(String beanName) {
Map<String, MyBeanDefinition> beanDefinitionMap = this.registry.beanDefinitionMap;
//获取beanDefinition
MyBeanDefinition myBeanDefinition = beanDefinitionMap.get(beanName);
if(myBeanDefinition == null) {return null;}
if(null != getSingleton(beanName,myBeanDefinition)){
return getSingleton(beanName,myBeanDefinition);
}
//标记对象创建中
singletonCurrentlyInCreation.add(beanName);
//反射实例化
Object instance = instantiateBean(beanName, myBeanDefinition);
//包装Bean
MyBeanWrapper myBeanWrapper = new MyBeanWrapper(instance, instance.getClass());
//依赖注入
populateBean(myBeanWrapper);
singletonCurrentlyInCreation.remove(beanName);
singletonObject.put(beanName,instance);
earlySingletonObject.remove(beanName);
//保存到ioc容器中
this.factoryBeanInstanceCache.put(beanName, myBeanWrapper);
return myBeanWrapper.getWrappedInstance();
}
private Object getSingleton(String beanName,MyBeanDefinition myBeanDefinition) {
//从一级缓存取bean
Object singletonObject = this.singletonObject.get(beanName);
//一级bean为null,存在两种情况:bean从未创建过或者bean正在创建中,通过标记容器判断
if(null == singletonObject && singletonCurrentlyInCreation.contains(beanName)){
//存在循环依赖
//从二级缓存取bean
singletonObject = earlySingletonObject.get(beanName);
if(null == singletonObject){
//从三级缓存取bean
singletonObject = instantiateBean(beanName,myBeanDefinition);
//二级缓存放入
earlySingletonObject.put(beanName,singletonObject);
//三级缓存移除
factoryBeanObjectCache.remove(beanName);
}
}
return singletonObject;
}
private void populateBean(MyBeanWrapper myBeanWrapper) {
Object wrappedInstance = myBeanWrapper.getWrappedInstance();
Class<?> wrappedClazz = myBeanWrapper.getWrappedClazz();
//获取类对象下所有字段,根据是否存在注解@MyAutowired决定是否进行依赖注入
for (Field field : wrappedClazz.getDeclaredFields()) {
if (!field.isAnnotationPresent(MyAutowired.class)) {
continue;
}
//自定义beanName
String defineBeanName = field.getAnnotation(MyAutowired.class).value();
//默认以字段类型首字母小写作为beanName
String beanName = StringUtil.firstCaseToLower(field.getType().getSimpleName());
//类全限定名作为beanName
String fullBeanName = field.getType().getName();
//暂存默认beanName
String simpleBeanName = beanName;
//标志defineBeanName是否为空
boolean flag = true;
if (!StringUtil.isEmpty(defineBeanName)) {
beanName = defineBeanName;
flag = false;
}
if (!flag) {
if (null == getBean(beanName)) {
beanName = simpleBeanName;
}
}
if (null == getBean(beanName)) {
beanName = fullBeanName;
}
ReflectUtil.fieldSetting(field, wrappedInstance, getBean(beanName));
}
}
private Object instantiateBean(String beanName, MyBeanDefinition myBeanDefinition) {
if(myBeanDefinition.isSingleton() && this.factoryBeanObjectCache.containsKey(beanName)){
return this.factoryBeanObjectCache.get(beanName);
}
try {
Class<?> clazz = Class.forName(myBeanDefinition.getBeanClassName());
Object instance = clazz.newInstance();
//如果是代理对象,触发AOP的逻辑
if(myBeanDefinition.isSingleton()){
if(!StringUtil.firstCaseToLower(Class.forName(myBeanDefinition.getBeanClassName()).getSimpleName()).equals(beanName)){
this.factoryBeanObjectCache.put(StringUtil.firstCaseToLower(Class.forName(myBeanDefinition.getBeanClassName()).getSimpleName()), instance);
}
this.factoryBeanObjectCache.put(beanName, instance);
this.factoryBeanObjectCache.put(myBeanDefinition.getBeanClassName(), instance);
}
return instance;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public Object getBean(Class clazz) {
return getBean(clazz.getName());
}
public int getBeanDefinitionCount() {
return this.registry.beanDefinitionMap.size();
}
public String[] getBeanDefinitionNames() {
return this.registry.beanDefinitionMap.keySet().toArray(new String[]{});
}
public MyBeanDefinition getBeanDefinitionByName(String beanName) {
return this.registry.beanDefinitionMap.get(beanName);
}
}