定义扫描路径
-
创建ApplicationContext类
package com.smile.spring; public class ApplicationContext {}
-
采用配置类加注解实现配置功能
- 创建配置类
package com.smile.main; public class ApplicationConfig {}
- 创建注解
package com.smile.spring; import java.lang.annotation.Target; import java.lang.annotation.Retention; import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; /** * @author yiwenjie * 设置扫描的路径地址 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface ComponentScan { String value() default ""; }
-
根据设定的路径,扫描指定文件
package com.smile.spring; import java.io.File; import java.net.URL; /** * @author yiwenjie * 应用容器 */ public class ApplicationContext { /** * 配置文件类 **/ private Class configClass; /** * 加载配置文件 **/ public ApplicationContext(Class configClass) throws ClassNotFoundException { this.configClass = configClass; //判断配置文件中,是否存在ComponentScan注解 if (!configClass.isAnnotationPresent(ComponentScan.class)) { throw new RuntimeException("配置文件异常"); } //获取到ComponentScan注解 //强制转换成ComponentScan注解 ComponentScan componentScan = (ComponentScan) configClass.getAnnotation(ComponentScan.class); //获取到ComponentScan注解定义的路径 String scanPath = componentScan.value(); if (scanPath == null || scanPath.length() == 0) { throw new RuntimeException("配置文件设置的路径地址异常"); } //将设置的路由转换成文件路径的格式 scanPath = scanPath.replace(".","/"); //获取到类的加载器 ClassLoader classLoader = ApplicationContext.class.getClassLoader(); //根据类加载器,获取到扫描路径的绝对地址 URL resource = classLoader.getResource(scanPath); if (resource == null) { throw new RuntimeException("路由地址异常"); } //判断绝对地址是否是一个目录 File fileDirectory = new File(resource.getPath()); if (!fileDirectory.isDirectory()) { throw new RuntimeException("路由地址不是一个目录"); } //获取到文件夹下所有文件 for (File file : fileDirectory.listFiles()) { String fileName = file.getAbsolutePath(); //判断文件是否以.class结尾 if (fileName.endsWith(".class")) { //将文件名转换成正常的文件类名描述 fileName = fileName.replace("/","."); String className = fileName.substring(fileName.indexOf("com"),fileName.indexOf(".class")); //获取到文件对应的Class类 Class fileClass = classLoader.loadClass(className); //判断Class是否包含Component注解 if (fileClass.isAnnotationPresent(Component.class)) { //获取到Component标识的bean名称 String beanName = ((Component) fileClass.getAnnotation(Component.class)).value(); System.out.println(beanName); } } } } }
-
创建UserService
package com.smile.main; import com.smile.spring.Component; /** * @author yiwenjie */ @Component("userService") public class UserService { }
-
创建启动类Application
package com.smile.main; import com.smile.spring.ApplicationContext; import java.lang.reflect.InvocationTargetException; /** * @author yiwenjie */ public class Application { public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { //解析配置文件 ApplicationContext context = new ApplicationContext(ApplicationConfig.class); } }
-
输出结果如下:
创建Bean
-
创建BeanDefinition类,用来记录bean的信息
package com.smile.spring; /** * @author yiwenjie * Bean定义类 */ public class BeanDefinition { /** * 记录bean的类型,是单例,还是非单例 **/ private String type; /** * 保存Class信息 **/ private Class context; public String getType() { return type; } public void setType(String type) { this.type = type; } public Class getContext() { return context; } public void setContext(Class context) { this.context = context; } }
-
创建Scope注解来标识类是单例,还是多例模式
package com.smile.spring; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author yiwenjie * 标明实例类型 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Scope { String value() default "singleton"; }
-
创建
package com.smile.spring; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.util.HashMap; import java.util.Objects; /** * @author yiwenjie * 应用容器 */ public class ApplicationContext { /** * 配置文件类 **/ private Class configClass; /** * 用来保存bean **/ private HashMap<String,BeanDefinition> beanDefinitionHashMap = new HashMap<>(); /** * 用来保存单例的类 **/ private HashMap<String,Object> singletonBeanHashMap = new HashMap<>(); /** * 加载配置文件 **/ public ApplicationContext(Class configClass) throws ClassNotFoundException { this.configClass = configClass; //判断配置文件中,是否存在ComponentScan注解 if (!configClass.isAnnotationPresent(ComponentScan.class)) { throw new RuntimeException("配置文件异常"); } //获取到ComponentScan注解 //强制转换成ComponentScan注解 ComponentScan componentScan = (ComponentScan) configClass.getAnnotation(ComponentScan.class); //获取到ComponentScan注解定义的路径 String scanPath = componentScan.value(); if (scanPath == null || scanPath.length() == 0) { throw new RuntimeException("配置文件设置的路径地址异常"); } //将设置的路由转换成文件路径的格式 scanPath = scanPath.replace(".","/"); //获取到类的加载器 ClassLoader classLoader = ApplicationContext.class.getClassLoader(); //根据类加载器,获取到扫描路径的绝对地址 URL resource = classLoader.getResource(scanPath); if (resource == null) { throw new RuntimeException("路由地址异常"); } //判断绝对地址是否是一个目录 File fileDirectory = new File(resource.getPath()); if (!fileDirectory.isDirectory()) { throw new RuntimeException("路由地址不是一个目录"); } //获取到文件夹下所有文件 for (File file : fileDirectory.listFiles()) { String fileName = file.getAbsolutePath(); //判断文件是否以.class结尾 if (fileName.endsWith(".class")) { //将文件名转换成正常的文件类名描述 fileName = fileName.replace("/","."); String className = fileName.substring(fileName.indexOf("com"),fileName.indexOf(".class")); //获取到文件对应的Class类 Class fileClass = classLoader.loadClass(className); //判断Class是否包含Component注解 if (fileClass.isAnnotationPresent(Component.class)) { //获取到Component标识的bean名称 String beanName = ((Component) fileClass.getAnnotation(Component.class)).value(); //初始化一个BeanDefinition类 BeanDefinition beanDefinition = new BeanDefinition(); beanDefinition.setContext(fileClass); //判断是否存在Scope注解 //默认情况下给予单例的模式 if (fileClass.isAnnotationPresent(Scope.class)) { beanDefinition.setType(((Scope) fileClass.getAnnotation(Scope.class)).value()); } else { beanDefinition.setType("singleton"); } //将生成好的beanDefinition保存到beanMap中 beanDefinitionHashMap.put(beanName,beanDefinition); } } } //实例出所有的单例bean beanDefinitionHashMap.forEach((k,v) -> { if (v.getType().equals("singleton")) { try { singletonBeanHashMap.put(k,v.getContext().getConstructor().newInstance()); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } }); } /** * 创建bean **/ public Object createBean(String beanName,BeanDefinition beanDefinition) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { //判断需要实例化的类是不是单例 if ("singleton".equals(beanDefinition.getType())) { return singletonBeanHashMap.get(beanName); } return beanDefinition.getContext().getConstructor().newInstance(); } /** * 获取到bean **/ public Object getBean(String beanName) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { return createBean(beanName,beanDefinitionHashMap.get(beanName)); } }