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

本例在 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);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值