手动实现spring的容器机制==超简化版:只做参考

    技术2025-11-17  17

    本例在 springmvc 中实现,围绕三步进行: (1):定位:配置文件,读取扫描路径,保存扫描到的类 (2):加载:读取扫描路径,保存扫描到的类 (3):注册:注册扫描到的类

    环境说明:

    webapp----》WEB-INF:

    <servlet> <servlet-name>qingnianmvc</servlet-name> <servlet-class>com.qingnian.spring.controller.DispatchServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.properties</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>qingnianmvc</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>

    classpath: 下生成对应的配置文件applicationContext.properties

    #所要扫描的包路径 spring.scan=com.qingnian.demo

    仿造 spring 生成自定义注解

    import java.lang.annotation.*; /* 任涛 -----专用 */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyService { String value() default ""; } import java.lang.annotation.*; /* 任涛 -----专用 */ @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyRequestParam { String value() default ""; } import java.lang.annotation.*; /* 任涛 -----专用 */ @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyRequestMapping { String value() default ""; } import java.lang.annotation.*; /* 任涛 -----专用 */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyController { String value() default ""; } import java.lang.annotation.*; /* 任涛 -----专用 */ @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyAutowried { String value() default ""; }

    核心类:DispatchServlet

    import com.qingnian.demo.controller.StudentController; import com.qingnian.spring.annotaion.MyAutowried; import com.qingnian.spring.annotaion.MyController; import com.qingnian.spring.annotaion.MyService; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.net.URL; import java.util.*; /* 任涛 -----专用 */ public class DispatchServlet extends HttpServlet { //配置文件 private Properties contextConfig=new Properties(); //存放包扫描扫描到的class全路径名称 private List<String> classNames=new ArrayList<>(); //存放<对象名称,对象本身>map (可理解为一个容器) //spring 中存放的是对象的定义,而不是对象 private Map<String,Object> beanMap=new HashMap<>(); @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //super.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("执行了doPost方法"); } @Override public void init(ServletConfig config) throws ServletException { //初始化开始 //定位配置文件 doLoadCongig(config.getInitParameter("contextConfigLocation")); //加载配置文件中的内容 doScanner(contextConfig.getProperty("spring.scan")); //注册对象 doInstance(); //自动注入 doAutowired(); //测试 StudentController studentController = (StudentController) beanMap.get("studentController"); String student = studentController.getOne("ceshi:1"); System.out.println(student); //如果为springmvc ,会多一个 HandlerMapping 组件,用于存放<url,controller> //将对应的mapping路径,对应方法保存在map中,前端发送请求过来时,快速定位执行 initHandlerMapping(); } private void initHandlerMapping() { } private void doAutowired() { if(null==beanMap){ return; } //遍历beanMap :判断对象的属性是否需要注入对应对象 beanMap.forEach((k,entity)->{ Field[] fields = entity.getClass().getDeclaredFields(); for (Field field : fields) { if(field.isAnnotationPresent(MyAutowried.class)){ //需要自动注入 MyAutowried autowried = field.getAnnotation(MyAutowried.class); String autoBeanname= autowried.value().trim(); if("".equals(autoBeanname)){ //默认填充的对象名称:首字母小写 autoBeanname=lowercase(field.getType().getSimpleName()); } //为字段注入内容 field.setAccessible(true); try { field.set(entity, beanMap.get(autoBeanname)); } catch (IllegalAccessException e) { e.printStackTrace(); } } } }); } private void doInstance() { if(null==classNames){ return; } for (String className : classNames) { //通过反射构建对象 try { Class<?> aClass = Class.forName(className); if (aClass.isAnnotationPresent(MyController.class)){ //为有 @MyController 注解修饰的Java类生成对应的对象 //首字母小写 String beanName=lowercase(aClass.getSimpleName()); beanMap.put(beanName,aClass.newInstance()); }else if(aClass.isAnnotationPresent(MyService.class)){ MyService myService = aClass.getAnnotation(MyService.class); //获取注解中的value值:如果有指定值。则不用默认首字母小写策略 String beanName = myService.value(); if ("".equals(beanName.trim())){ beanName=lowercase(aClass.getSimpleName()); } beanMap.put(beanName,aClass.newInstance()); //判断该类是否为有实现接口 Class<?>[] interfaces = aClass.getInterfaces(); for (Class<?> anInterface : interfaces) { //遍历所实现的接口,生成对应<接口名称,实现类对象> beanMap.put(lowercase(anInterface.getSimpleName()),aClass.newInstance()); } }else{ continue; } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } } } //首字母小写的方法 private String lowercase(String beanName) { char[] chars = beanName.toCharArray(); chars[0]+=32; return String.valueOf(chars); } //扫描指定包路径,将对应的完整类名放入list private void doScanner(String packageName) { URL url = this.getClass().getClassLoader().getResource("/" + packageName.replaceAll("\\.", "/")); File filedir=new File(url.getFile()); for (File file : filedir.listFiles()) { if(file.isDirectory()){ doScanner(packageName+"."+file.getName()); }else { classNames.add(packageName+"."+file.getName().replaceAll(".class","")); } } } private void doLoadCongig(String location) { //spring -> reader 解析器读取配置文件的内容 InputStream stream = this.getClass().getClassLoader().getResourceAsStream(location.replace("classpath:", "")); try { contextConfig.load(stream); } catch (IOException e) { e.printStackTrace(); } finally { if (null != stream) { try { stream.close(); } catch (IOException e) { e.printStackTrace(); } } } } }

    下面是测试代码:

    package com.qingnian.demo.service; /* 任涛 -----专用 */ public interface StudentService { String selectOne(String id); } package com.qingnian.demo.service.impl; import com.qingnian.demo.service.StudentService; import com.qingnian.spring.annotaion.MyService; /* 任涛 -----专用 */ @MyService public class StudentServiceImpl implements StudentService { @Override public String selectOne(String id) { return "StudentServiceImpl返回学生1:"+id; } } package com.qingnian.demo.controller; import com.qingnian.demo.service.StudentService; import com.qingnian.spring.annotaion.MyAutowried; import com.qingnian.spring.annotaion.MyController; import com.qingnian.spring.annotaion.MyRequestMapping; import com.qingnian.spring.annotaion.MyRequestParam; /* 任涛 -----专用 */ @MyController @MyRequestMapping("Student") public class StudentController { @MyAutowried private StudentService studentService; @MyRequestMapping("/get/id") public String getOne(@MyRequestParam("id")String id){ return studentService.selectOne(id); } }
    Processed: 0.033, SQL: 9