我们知道Spring初始化IOC容器顺序是:
1、定位配置文件
2、加载配置文件
3、注册并初始化bean
编写Servlet类,继承HttpServlet,重新Init()方法,在init()方法中加载配置文件,扫描相关类,初始化IOC容器,依赖注入,初始化handerMapping等。
public class MyDispatcherServlet extends HttpServlet {
private static final String LOCATION = "contextConfigLocation";
private Properties properties = new Properties();
private List classNameList = new ArrayList<>();
private Map IOC = new HashMap<>();
private List handlerMapping = new ArrayList<>();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws
ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws
ServletException, IOException {
doDispath(req, resp);
}
@Override
public void init(ServletConfig config) throws ServletException {
//1、加载配置文件
doLoadConfig(config.getInitParameter(LOCATION));
//2、扫描相关类
doScan(properties.getProperty("scanPackage"));
//3、初始化相关类,并放入到IOC容器中
doInstance();
//4、完成依赖注入
doAutoWired();
//5、初始化HanderMapping
initHanderMapping();
System.out.println("初始化完成!");
}
@Override
public void init() throws ServletException {
super.init();
}
}
加载配置文件
/**
* @Description 加载配置文件
* @param configPath
* @return void
* @Date 2019/7/14 21:15
*/
private void doLoadConfig(String configPath){
InputStream is = this.getClass().getClassLoader().getResourceAsStream(configPath);
try {
properties.load(is);
} catch (Exception e){
e.printStackTrace();
} finally {
if (is!=null){
try {
is.close();
}catch (Exception ex){
ex.printStackTrace();
}
}
}
}
扫描相关类
private void doScan(String packageName){
//将包路径转换为文件路径
URL url = this.getClass().getClassLoader().getResource("/"+packageName.replaceAll("\\.","/"));
File classPath = new File(url.getFile());
for (File file : classPath.listFiles()){
if(file.isDirectory()){
doScan(packageName + "." + file.getName());
}else {
if(!file.getName().endsWith(".class")){
continue;
}
classNameList.add(packageName + "." + file.getName().replaceAll(".class",""));
}
}
}
初始化类
private void doInstance(){
if(classNameList.isEmpty())
return;
try {
for (String className : classNameList){
Class> clazz = Class.forName(className);
//只需要初始化带有MyController和MyService
String name = clazz.getSimpleName();
if(clazz.isAnnotationPresent(MyController.class)){
Object instance = clazz.newInstance();
name = lowerFirstChar(name);
IOC.put(name,instance);
}else if(clazz.isAnnotationPresent(MyService.class)){
//1、默认类名首字母小写
String beanName = lowerFirstChar(name);
//2、自定义类名
MyService service = clazz.getAnnotation(MyService.class);
if(!"".equals(service.value())){
beanName = service.value();
IOC.put(beanName,clazz.newInstance());
continue;
}
//3、根据类型自动赋值
//?????????????????
Class>[] intencefaces = clazz.getInterfaces();//获得接口的实现类
for (Class> i : intencefaces){
IOC.put(i.getName(),clazz.newInstance());
}
}else{
continue;
}
}
}catch (Exception e){
e.printStackTrace();
}
}
自动依赖注入
private void doAutoWired() {
if(IOC.isEmpty())
return;
for (Map.Entry entry : IOC.entrySet()){
Field [] fileds = entry.getValue().getClass().getDeclaredFields();
for (Field field : fileds){
if(!field.isAnnotationPresent(MyAutoWired.class))
continue;
MyAutoWired autoWired = field.getAnnotation(MyAutoWired.class);
String beanname = autoWired.value().trim();
if("".equals(beanname)){
beanname = field.getType().getName();
}
field.setAccessible(true);
try {
//利用反射给字段赋值,实现自动注入依赖对象
field.set(entry.getValue(),IOC.get(beanname));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
初始化HandlerMapping
private void initHanderMapping() {
if(IOC.isEmpty())
return;
String url = "";
for(Map.Entry entry : IOC.entrySet()){
Class> clazz = entry.getValue().getClass();
if(!clazz.isAnnotationPresent(MyController.class))
continue;
//获取Controller上的MyRequestMapping中的url配置
if(clazz.isAnnotationPresent(MyRequestMapping.class)){
MyRequestMapping requestMapping = clazz.getAnnotation(MyRequestMapping.class);
url = requestMapping.value();
}
Method[] methods = clazz.getMethods();
for (Method method : methods){
if(!method.isAnnotationPresent(MyRequestMapping.class))
continue;
MyRequestMapping requestMapping = method.getAnnotation(MyRequestMapping.class);
String reqex = ("/" + url + "/"+requestMapping.value()).replaceAll("/+","/");
Pattern pattern = Pattern.compile(reqex);
handlerMapping.add(new Handler(entry.getValue(),method,pattern));
}
}
}
private Handler getHandler(HttpServletRequest req) throws Exception{
if(handlerMapping.isEmpty())
return null;
String url = req.getRequestURI();
String contextPath = req.getContextPath();
url = url.replace(contextPath, "").replaceAll("/+", "/");
for (Handler handler : handlerMapping) {
try{
Matcher matcher = handler.pattern.matcher(url);
//如果没有匹配上继续下一个匹配
if(!matcher.matches())
continue;
return handler;
}catch(Exception e){
throw e;
}
}
return null;
}
//内部类
private class Handler {
//保存方法对应的实例
protected Object controller;
//保存映射的方法
protected Method method;
protected Pattern pattern;
//方法参数顺序
protected Map paramIndexMapping;
public Handler(Object controller, Method method, Pattern pattern) {
this.controller = controller;
this.method = method;
this.pattern = pattern;
paramIndexMapping = new HashMap();
putMethodParamIndex(method);
}
private void putMethodParamIndex(Method method) {
Annotation[][] annotations = method.getParameterAnnotations();
//获取方法参数中加了MyRequestParam的注解
for (int i=0;i [] paramsTypes = method.getParameterTypes();
for (int i = 0; i < paramsTypes.length ; i ++) {
Class> type = paramsTypes[i];
if(type == HttpServletRequest.class ||
type == HttpServletResponse.class){
paramIndexMapping.put(type.getName(),i);
}
}
}
}
//只需要把String转换为任意类型就好
private Object convert(Class> type,String value){
if(Integer.class == type){
return Integer.valueOf(value);
}
//如果还有double或者其他类型,继续加if
//这时候,我们应该想到策略模式了
//在这里暂时不实现,希望小伙伴自己来实现
return value;
}
//方法的具体处理
private void doDispath(HttpServletRequest req, HttpServletResponse resp) {
try {
Handler handler = getHandler(req);
if(handler == null){
//404错误
resp.getWriter().write("Resource Not Found,404!");
return;
}
//获取方法的参数列表
Class> [] paramTypes = handler.method.getParameterTypes();
Object [] paramValues = new Object[paramTypes.length];
Map params = req.getParameterMap();
for (Map.Entry param : params.entrySet()){
String value = Arrays.toString(param.getValue()).replaceAll("\\[|\\]", "").replaceAll(",\\s", ",");
if(!handler.paramIndexMapping.containsKey(param.getKey())){continue;}
int index = handler.paramIndexMapping.get(param.getKey());
paramValues[index] = convert(paramTypes[index],value);
}
//设置方法中的request和response对象
int reqIndex = handler.paramIndexMapping.get(HttpServletRequest.class.getName());
paramValues[reqIndex] = req;
int respIndex = handler.paramIndexMapping.get(HttpServletResponse.class.getName());
paramValues[respIndex] = resp;
Object res = handler.method.invoke(handler.controller, paramValues);
if(res instanceof Void)
return;
resp.getWriter().write(res.toString());
} catch (Exception e) {
e.printStackTrace();
}
}