package cn.nosum.framework.context; import cn.nosum.framework.annotation.Autowired; import cn.nosum.framework.annotation.Controller; import cn.nosum.framework.annotation.Service; import cn.nosum.framework.beans.BeanDefinition; import cn.nosum.framework.beans.BeanWrapper; import cn.nosum.framework.beans.support.BeanDefinitionReader; import java.lang.reflect.Field; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; public class ApplicationContext { protected final Map beanDefinitionMap=new ConcurrentHashMap(); private String[] configLocations; private BeanDefinitionReader reader; private Map factoryBeanObjectCache=new ConcurrentHashMap(); private Map factoryBeanInstanceCache=new ConcurrentHashMap(); public ApplicationContext(String... configLocations){ this.configLocations=configLocations; try { // 定位 reader=new BeanDefinitionReader(this.configLocations); // 加载配置文件,扫描相关的类,包装为 BeanDefinition ListbeanDefinitions=reader.loadBeanDefinitions(); // 注册,将配置信息放到容器中 doRegistryBeanDefinition(beanDefinitions); // 依赖注入 doAutowired(); }catch (Exception e){e.printStackTrace();} } private void doRegistryBeanDefinition(List beanDefinitions) throws Exception { for (BeanDefinition beanDefinition : beanDefinitions) { if (this.beanDefinitionMap.containsKey(beanDefinition.getFactoryBeanName())){ throw new Exception("The Bean " + beanDefinition.getFactoryBeanName() + "is exists!!"); } this.beanDefinitionMap.put(beanDefinition.getFactoryBeanName(),beanDefinition); this.beanDefinitionMap.put(beanDefinition.getBeanClassName(),beanDefinition); } } private void doAutowired() { for (Map.Entry beanDefinitionEntry : this.beanDefinitionMap.entrySet()) { String beanName=beanDefinitionEntry.getKey(); try { getBean(beanName); }catch (Exception e){e.printStackTrace();} } } private Object getBean(Class beanClass) { return getBean(beanClass.getName()); } private Object getBean(String beanName) { // 读取配置信息 BeanDefinition beanDefinition=this.beanDefinitionMap.get(beanName); // 将对象封装到 BeanDefinitionWrapper 中 BeanWrapper beanWrapper=new BeanWrapper(instantiateBean(beanDefinition)); // 缓存 this.factoryBeanInstanceCache.put(beanName,beanWrapper); // 依赖注入 populateBean(beanName,beanDefinition,beanWrapper); return this.factoryBeanInstanceCache.get(beanName).getWrapperInstance(); } private void populateBean(String beanName, BeanDefinition beanDefinition, BeanWrapper beanWrapper) { //可能涉及到循环依赖? //A{ B b} //B{ A b} //用两个缓存,循环两次 //1、把第一次读取结果为空的BeanDefinition存到第一个缓存 //2、等第一次循环之后,第二次循环再检查第一次的缓存,再进行赋值 Object instance = beanWrapper.getWrapperInstance(); Class clazz = beanWrapper.getWrappedClass(); //在Spring中@Component if(!(clazz.isAnnotationPresent(Controller.class) || clazz.isAnnotationPresent(Service.class))){ return; } //把所有的包括private/protected/default/public 修饰字段都取出来 for (Field field : clazz.getDeclaredFields()) { if(!field.isAnnotationPresent(Autowired.class)){ continue; } Autowired autowired = field.getAnnotation(Autowired.class); //如果用户没有自定义的beanName,就默认根据类型注入 String autowiredBeanName = autowired.value().trim(); if("".equals(autowiredBeanName)){ //field.getType().getName() 获取字段的类型 autowiredBeanName = field.getType().getName(); } //暴力访问 field.setAccessible(true); try { if(this.factoryBeanInstanceCache.get(autowiredBeanName) == null){ continue; } field.set(instance,this.factoryBeanInstanceCache.get(autowiredBeanName).getWrapperInstance()); } catch (IllegalAccessException e) { e.printStackTrace(); continue; } } } private Object instantiateBean(BeanDefinition beanDefinition) { // 取得实例化对象的类名 String className=beanDefinition.getBeanClassName(); Object instance=null; try{ if (this.factoryBeanObjectCache.containsKey(className)){ instance=this.factoryBeanObjectCache.get(className); }else{ Class clazz=Class.forName(className); instance=clazz.getDeclaredConstructor().newInstance(); this.factoryBeanObjectCache.put(className,instance); this.factoryBeanObjectCache.put(beanDefinition.getFactoryBeanName(),instance); } }catch (Exception e){e.printStackTrace();} return instance; } public String[] getBeanDefinitionNames(){ return this.beanDefinitionMap.keySet().toArray(new String[getBeanDefinitionCount()]); } public int getBeanDefinitionCount(){ return this.beanDefinitionMap.size(); } public Properties getConfig(){ return this.reader.getConfig(); } }