标签:而且 one hashmap 获取 try alac 完成 with interface
效仿原生AapplicationContext 简单的源码分为构造方法和getBean方法所以我们需要冲着些方法考虑
基本完成的代码如下
AapplicationContext 类如下
package cn.jiedada.spring; import java.io.File; import java.lang.annotation.Annotation; import java.net.URL; import java.util.HashMap; import java.util.Map; public class JieDaDaApplicationContext { private Class configClass; //在getBean中通过名字找到对象 private Map<String,BeanDefinition> beanDefinitionMap = new HashMap<>(); //单列池,里面的是currenthashmap private Map<String,Object> singletonObjects = new HashMap<>(); public JieDaDaApplicationContext(Class configClass) { this.configClass = configClass; //解析配置类 scopCompenent(configClass); //实力化创建单列bean并且保存 preInstantiateSingleton(); } private void preInstantiateSingleton() { for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) { BeanDefinition beanDefinition = entry.getValue(); String beanName = entry.getKey(); //我们这里只保留单列的bean,因为多列的创建为使用时候在创建,而且不知道多列能够创建多少 if ("singleton".equals(beanDefinition.getScope())){ //如果为单列就创建bean Object bean = createBean(beanName, beanDefinition); singletonObjects.put(beanName,bean); } } } //创建bean的方法 public Object createBean(String beanName,BeanDefinition beanDefinition){ Class clazz = beanDefinition.getClazz(); Object instance = null; try { instance = clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return instance; } private void scopCompenent(Class configClass) { ComponentScan annotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class); //扫秒路径 String path = annotation.value();//cn.jiedada String replace = path.replace(".", "/"); //扫描component类 1.单列 2.多列 //通过类加载器获得文件路径 ClassLoader classLoader = JieDaDaApplicationContext.class.getClassLoader(); URL resource = classLoader.getResource(replace); File file = new File(resource.getFile()); File[] files = file.listFiles(); //遍历文件判断是否包含component注解 for (File f : files) { //文件路径 String filePath = f.getAbsolutePath(); //判断是否是含有.class if (filePath.endsWith(".class")){ //获得真实路径 String realPath1 = filePath.substring(filePath.indexOf("cn"), filePath.indexOf(".class")); //通过类加载器获得对象应为类加载器需要使用的路径不为cn/jiedada/test/Main需要转化 String fileRealPath = realPath1.replace("/", "."); try { Class clazz = classLoader.loadClass(fileRealPath); //获得component类对象 //获得类对象需要判断多列和单列所以需要添加一个注解 //因为是通过getBean获得对象,所以不可能再去getBean中在遍历一次,所以我们需要把对象保存BeanDefinition //又因为通过名字获得对象所以需要通过先存入Map对象的方式实现 if(clazz.isAnnotationPresent(Component.class)){ Component component = (Component) clazz.getAnnotation(Component.class); //保存beanDefinitionMap BeanDefinition beanDefinition = new BeanDefinition(); beanDefinition.setClazz(clazz); if (clazz.isAnnotationPresent(Scope.class)){ //设置类的scope Scope scope = (Scope) clazz.getAnnotation(Scope.class); String value = scope.value(); beanDefinition.setScope(value); }else { beanDefinition.setScope("singleton"); } beanDefinitionMap.put(component.value(),beanDefinition); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } } public Object getBean(String beanName){ //获得beanDefinition if (beanDefinitionMap.containsKey(beanName)){ BeanDefinition beanDefinition = beanDefinitionMap.get(beanName); if (beanDefinition.getScope().equals("singleton")){ //单列 Object o = singletonObjects.get(beanName); return o; }else { //多列 Object bean = createBean(beanName, beanDefinition); return bean; } }else { throw new RuntimeException(); } } }
里面分为构造方法和getBean方法
JieDaDaApplicationContext context = new JieDaDaApplicationContext(AppConfig.class);
扫描路径获得我们需要生成对象的范围所以需要一个注解
CompenentScan
package cn.jiedada.spring; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ComponentScan { String value() default ""; }
以及AppConfig类
package cn.jiedada.test; import cn.jiedada.spring.ComponentScan; @ComponentScan("cn.jiedada.test") public class AppConfig { }
这样我们才知道我们需要把什么包下面的对象交给Spring管理
ComponentScan annotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class); //扫秒路径 String path = annotation.value();//cn.jiedada
通过类加载器获得.class文件
//通过类加载器获得文件路径 ClassLoader classLoader = JieDaDaApplicationContext.class.getClassLoader(); URL resource = classLoader.getResource(replace); File file = new File(resource.getFile()); File[] files = file.listFiles();
遍历文件判断是否含有Component注解,这个注解表示生成的对象名称
Component注解
package cn.jiedada.spring; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Component { String value() default ""; }
这里就需要把对象的beanName,class对象和是否为单列保存到一个map对象中去,因为如果不在构造方法中保存的话,在getBean方法中就需要在便利
private Map<String,BeanDefinition> beanDefinitionMap = new HashMap<>();
for (File f : files) { //文件路径 String filePath = f.getAbsolutePath(); //判断是否是含有.class if (filePath.endsWith(".class")){ //获得真实路径 String realPath1 = filePath.substring(filePath.indexOf("cn"), filePath.indexOf(".class")); //通过类加载器获得对象应为类加载器需要使用的路径不为cn/jiedada/test/Main需要转化 String fileRealPath = realPath1.replace("/", "."); try { Class clazz = classLoader.loadClass(fileRealPath); //获得component类对象 //获得类对象需要判断多列和单列所以需要添加一个注解 //因为是通过getBean获得对象,所以不可能再去getBean中在遍历一次,所以我们需要把对象保存BeanDefinition //又因为通过名字获得对象所以需要通过先存入Map对象的方式实现 if(clazz.isAnnotationPresent(Component.class)){ Component component = (Component) clazz.getAnnotation(Component.class); //保存beanDefinitionMap BeanDefinition beanDefinition = new BeanDefinition(); beanDefinition.setClazz(clazz); if (clazz.isAnnotationPresent(Scope.class)){ //设置类的scope Scope scope = (Scope) clazz.getAnnotation(Scope.class); String value = scope.value(); beanDefinition.setScope(value); }else { beanDefinition.setScope("singleton"); } beanDefinitionMap.put(component.value(),beanDefinition); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
所以需要一个存放class对象和是否为单列的一个新对象为beanDeefinition
BeanDeefinition类为
package cn.jiedada.spring; public class BeanDefinition { private Class clazz; private String scope; public Class getClazz() { return clazz; } public void setClazz(Class clazz) { this.clazz = clazz; } public String getScope() { return scope; } public void setScope(String scope) { this.scope = scope; } }
和一个注解Scope
package cn.jiedada.spring; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Scope { String value() default ""; }
上面整个步骤为解析配置类方法
解析过后就需要实力化对象因为涉及多列和单列所以当为单列的时候需要一个单列池保存对象
//单列池,里面的是currenthashmap private Map<String,Object> singletonObjects = new HashMap<>();
多列的时候就通过反射创建对象所以把创建对象的方法抽为一个方法
//创建bean的方法 public Object createBean(String beanName,BeanDefinition beanDefinition){ Class clazz = beanDefinition.getClazz(); Object instance = null; try { instance = clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return instance; }
通过初始化我们把所以的对象保存到了beanDeefinitionMap中??map获得对象并且存放单列池
private void preInstantiateSingleton() { for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) { BeanDefinition beanDefinition = entry.getValue(); String beanName = entry.getKey(); //我们这里只保留单列的bean,因为多列的创建为使用时候在创建,而且不知道多列能够创建多少 if ("singleton".equals(beanDefinition.getScope())){ //如果为单列就创建bean Object bean = createBean(beanName, beanDefinition); singletonObjects.put(beanName,bean); } } }
如果为单列就去单列池中获取如果不是就直接创建对象
public Object getBean(String beanName){ //获得beanDefinition if (beanDefinitionMap.containsKey(beanName)){ BeanDefinition beanDefinition = beanDefinitionMap.get(beanName); if (beanDefinition.getScope().equals("singleton")){ //单列 Object o = singletonObjects.get(beanName); return o; }else { //多列 Object bean = createBean(beanName, beanDefinition); return bean; } }else { throw new RuntimeException(); } }
这就是非常简单的Spring
标签:而且 one hashmap 获取 try alac 完成 with interface
原文地址:https://www.cnblogs.com/xiaoruirui/p/14807165.html