java controller注解原理_手写注解实现SpringMVC底层原理(虽简单却五脏俱全《注重思路》)...

手写注解实现SpringMVC底层原理

鄙人小白一个,还没毕业,就个人而言,搞IT这块,讲究思路。若对此文疑虑,评论来战。(本人->无期)

1.首先我们来搭建架构,就建一个普通的javaweb项目就OK了,具体目录如下:

3e36b56dbcb39d4da54ce22210bae754.png

对于小白来说可以细看后面web.xml的配置,对javaweb有点研究可以忽略而过后面的web.xml配置。

2.先上代码,运行起整个项目。再来聊聊思路。

e861a9f51b4da071c121ff4fd7d45ff1.png

(1).Controller注解

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.wuqi.annotation;import java.lang.annotation.*;/*** Created by wuqi on 2017/3/22.*/@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documentedpublic @interfaceController {

String value()default "";

}

Controller

(2).Quatifier注解

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.wuqi.annotation;import java.lang.annotation.*;/*** Created by wuqi on 2017/3/25.*/@Target({ ElementType.FIELD })//代表注解的注解

@Retention(RetentionPolicy.RUNTIME)

@Documentedpublic @interfaceQuatifier {

String value()default "";

}

Quatifier

(3).RequestMapping注解

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.wuqi.annotation;importjava.lang.annotation.Documented;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;/*** Created by Shock on 2017/3/22.*/@Target({ ElementType.METHOD })//在方法上的注解

@Retention(RetentionPolicy.RUNTIME)

@Documentedpublic @interfaceRequestMapping {

String value()default "";

}

RequestMapping

(4).Service注解

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.wuqi.annotation;importjava.lang.annotation.Documented;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;/*** Created by Shock on 2017/3/22.*/@Target({ ElementType.TYPE })

@Retention(RetentionPolicy.RUNTIME)

@Documentedpublic @interfaceService {

String value()default "";

}

Service

--------------------------------------------------------------------------------------------------------------------------

9004c40144cfcc53ed7e078bf0fe9aab.png

(1).MyService接口

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.wuqi.service.impl;importjava.util.Map;/*** Created by wuqi on 2017/3/23.*/

public interfaceMyService {intinsert(Map map);intdelete(Map map);intupdate(Map map);intselect(Map map);

}

MyService

(2).MyServiceImpl类

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.wuqi.service.impl;importcom.wuqi.annotation.Service;importjava.util.Map;/*** Created by wuqi on 2017/3/23.*/@Service("MyServiceImpl")public class MyServiceImpl implementsMyService {

@Overridepublic intinsert(Map map) {

System.out.println("MyServiceImpl:" + "insert");return 0;

}

@Overridepublic intdelete(Map map) {

System.out.println("MyServiceImpl:" + "delete");return 0;

}

@Overridepublic intupdate(Map map) {

System.out.println("MyServiceImpl:" + "update");return 0;

}

@Overridepublic intselect(Map map) {

System.out.println("MyServiceImpl:" + "select");return 0;

}

}

MyServiceImpl

(3).SpringmvcService接口

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.wuqi.service.impl;importjava.util.Map;/*** Created by wuqi on 2017/3/23.*/

public interfaceSpringmvcService {intinsert(Map map);intdelete(Map map);intupdate(Map map);intselect(Map map);

}

SpringmvcService

(4).MyServiceImpl类

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.wuqi.service.impl;importcom.wuqi.annotation.Service;importjava.util.Map;/*** Created by wuqi on 2017/3/23.*/@Service("SpringmvcServiceImpl")public class SpringmvcServiceImpl implementsSpringmvcService{

@Overridepublic intinsert(Map map) {

System.out.println("SpringmvcServiceImpl:" + "insert");return 0;

}

@Overridepublic intdelete(Map map) {

System.out.println("SpringmvcServiceImpl:" + "delete");return 0;

}

@Overridepublic intupdate(Map map) {

System.out.println("SpringmvcServiceImpl:" + "update");return 0;

}

@Overridepublic intselect(Map map) {

System.out.println("SpringmvcServiceImpl:" + "select");return 0;

}

}

SpringmvcServiceImpl

--------------------------------------------------------------------------------------------------------------------------

dfcbf7e1006d4e129c11881fd14b8685.png

(1).SpringmvcController类

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.wuqi.controller;import com.wuqi.annotation.*;importcom.wuqi.service.impl.MyService;importcom.wuqi.service.impl.SpringmvcService;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;/*** Created by wuqi on 2017/3/23.*/@Controller("wuqi")public classSpringmvcController {

@Quatifier("MyServiceImpl")

MyService myService;

@Quatifier("SpringmvcServiceImpl")

SpringmvcService smService;

@RequestMapping("insert")publicString insert(HttpServletRequest request, HttpServletResponse response, String param) {

myService.insert(null);

smService.insert(null);return null;

}

@RequestMapping("delete")publicString delete(HttpServletRequest request, HttpServletResponse response, String param) {

myService.delete(null);

smService.delete(null);return null;

}

@RequestMapping("update")publicString update(HttpServletRequest request, HttpServletResponse response, String param) {

myService.update(null);

smService.update(null);return null;

}

@RequestMapping("select")publicString select(HttpServletRequest request, HttpServletResponse response, String param) {

myService.select(null);

smService.select(null);return null;

}

}

SpringmvcController

--------------------------------------------------------------------------------------------------------------------------

e1c15d1bfb8a07ab075f8d7581412809.png

(1).DispatcherServlet类继承 javax.servlet.http.HttpServlet类

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.wuqi.servlet;import com.wuqi.annotation.*;importcom.wuqi.controller.SpringmvcController;importjava.io.File;importjava.io.IOException;importjava.lang.reflect.Field;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;importjava.net.URL;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importjavax.servlet.ServletConfig;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;/*** Created by Shock on 2017/3/23.*/

public class DispatcherServlet extendsHttpServlet{private static final long serialVersionUID = 1L;

List packageNames = new ArrayList();//所有类的实例,key是注解的value,value是所有类的实例

Map instanceMap = new HashMap();

Map handerMap = new HashMap();publicDispatcherServlet() {super();

}public void init(ServletConfig config) throwsServletException {//包扫描,获取包中的文件

scanPackage("com.wuqi");try{

filterAndInstance();

}catch(Exception e) {

e.printStackTrace();

}//建立映射关系

handerMap();//实现注入

ioc();

}private void filterAndInstance() throwsException {if (packageNames.size() <= 0) {return;

}for(String className : packageNames) {

Class> cName = Class.forName(className.replace(".class", "").trim());if (cName.isAnnotationPresent(Controller.class)) {

Object instance=cName.newInstance();

Controller controller= (Controller) cName.getAnnotation(Controller.class);

String key=controller.value();

instanceMap.put(key, instance);

}else if (cName.isAnnotationPresent(Service.class)) {

Object instance=cName.newInstance();

Service service= (Service) cName.getAnnotation(Service.class);

String key=service.value();

instanceMap.put(key, instance);

}else{continue;

}

}

}private voidioc() {if(instanceMap.isEmpty())return;for (Map.Entryentry : instanceMap.entrySet()) {//拿到里面的所有属性

Field fields[] =entry.getValue().getClass().getDeclaredFields();for(Field field : fields) {

field.setAccessible(true);//可访问私有属性

if (field.isAnnotationPresent(Quatifier.class));

Quatifier quatifier= field.getAnnotation(Quatifier.class);

String value=quatifier.value();

field.setAccessible(true);try{

field.set(entry.getValue(), instanceMap.get(value));

}catch(IllegalArgumentException e) {

e.printStackTrace();

}catch(IllegalAccessException e) {

e.printStackTrace();

}

}

}

SpringmvcController wuqi= (SpringmvcController) instanceMap.get("wuqi");

System.out.print(wuqi);

}/*** 扫描包下的所有文件

*

*@paramPackage*/

private voidscanPackage(String Package) {

URL url= this.getClass().getClassLoader().getResource("/" + replaceTo(Package));//将所有的.转义获取对应的路径

String pathFile =url.getFile();

File file= newFile(pathFile);

String fileList[]=file.list();for(String path : fileList) {

File eachFile= new File(pathFile +path);if(eachFile.isDirectory()) {

scanPackage(Package+ "." +eachFile.getName());

}else{

packageNames.add(Package+ "." +eachFile.getName());

}

}

}/*** 建立映射关系*/

private voidhanderMap() {if (instanceMap.size() <= 0)return;for (Map.Entryentry : instanceMap.entrySet()) {if (entry.getValue().getClass().isAnnotationPresent(Controller.class)) {

Controller controller= (Controller) entry.getValue().getClass().getAnnotation(Controller.class);

String ctvalue=controller.value();

Method[] methods=entry.getValue().getClass().getMethods();for(Method method : methods) {if (method.isAnnotationPresent(RequestMapping.class)) {

RequestMapping rm= (RequestMapping) method.getAnnotation(RequestMapping.class);

String rmvalue=rm.value();

handerMap.put("/" + ctvalue + "/" +rmvalue, method);

}else{continue;

}

}

}else{continue;

}

}

}privateString replaceTo(String path) {return path.replaceAll("\\.", "/");

}

@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException {this.doPost(req, resp);

}

@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException {

String url=req.getRequestURI();

String context=req.getContextPath();

String path= url.replace(context, "");

Method method=(Method) handerMap.get(path);

SpringmvcController controller= (SpringmvcController) instanceMap.get(path.split("/")[1]);try{

method.invoke(controller,new Object[] { req, resp, null});

}catch(IllegalAccessException e) {

e.printStackTrace();

}catch(IllegalArgumentException e) {

e.printStackTrace();

}catch(InvocationTargetException e) {

e.printStackTrace();

}

}

}

DispatcherServlet

所有的代码已经贴上,还有个web.xml

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

version="3.1">

testServlet

com.wuqi.servlet.DispatcherServlet

testServlet

/*

web.xml

3.好了代码已经贴上了,现在需要来说说思路,因为有代码了,所以用代码来将思路,这样更容易理解代码的含义。之后可以根据自己的程度去试着写。

首先我们需要扫描包中的所有文件(DispatcherServlet -> init(ServletConfig config) -> scanPackage("com.wuqi")),也就是含有注解的文件。然后将该包下的所有文件都存入packageNames集合中。

这时我们拿到了包下所有的文件,但我们只需要含有我们指定注解的那部分文件,因此需要过滤出我们想要的文件即可,并且在过滤的过程中,我们可以将过滤出来的类通过Class.forName来直接实例化并储存起来。存放到instanceMap集合中,并为其设置对应的key值,该key值就是类注解的value。

然后遍历instanceMap集合中的所有对象,获取指定注解的对象,并通过反射获取该对象的所有的方法,遍历所有的方法,将指定注解的方法存入handerMap,key为拼接字符串("/" + 对象变量名 + "/" + 方法名),value为方法(Method)。

然后我们可以遍历instanceMap集合中的所有对象,通过反射获取对象的所有属性值(字段)集合,然后遍历属性值集合,将属性值含有指定注解的,通过Field的set方法为该属性值赋值,这时就将对象注入了。(也就是往Controller中注入Service对象)

最后就可以通过反射的invoke方法调用某个对象的某个方法。(此时对象存于instanceMap,而方法都存于handerMap)

借鉴 -> http://blog.csdn.net/chaoyueygw/article/details/53393952该博文

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值