一、定义注解
package com.ayo.annotation;import java.lang.annotation.*;/** * 模拟springmvc的@Controller注解 */@Documented //JAVADOC@Target(ElementType.TYPE) //作用于类上@Retention(RetentionPolicy.RUNTIME) //限制Annotation的生命周期,我这里自定义的注解显然需要运行时保留public @interface Controller { /** * 作用于该类上的注解有一个value属性,说白了就是Controller的名称 * @return */ public String value();}
package com.ayo.annotation;import java.lang.annotation.*;/** * @Qualifier提供依赖注入 */@Documented@Target(ElementType.FIELD) //作用于字段上,实现注入@Retention(RetentionPolicy.RUNTIME)public @interface Qualifier { public String value();}
package com.ayo.annotation;import java.lang.annotation.*;/** * dao层注解 */@Documented@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Repository { public String value();}
package com.ayo.annotation;import java.lang.annotation.*;/** * RequestMapping提供url地址处理映射 */@Documented@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface RequestMapping { public String value();}
package com.ayo.annotation;import java.lang.annotation.*;/** * 业务层注解 */@Documented@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Service { public String value();}
二、写一个DispatcherServlet
package com.ayo.servlet;import com.ayo.annotation.*;import com.ayo.controller.UserController;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.annotation.WebInitParam;import javax.servlet.annotation.WebServlet;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.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.net.URL;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;@WebServlet(name = "dispatcherServlet", urlPatterns = "/*", loadOnStartup = 1, initParams = { @WebInitParam(name = "base-package", value = "com.ayo")})public class DispatcherServlet extends HttpServlet{ //扫描的基包 private String basePackage = ""; //基包下面所有的带包路径权限定类名 private ListpackageNames = new ArrayList (); //注解实例化,注解上的名称:实例化对象 private Map instanceMap = new HashMap (); //带包路径的权限定名称:注解上的名称 private Map nameMap = new HashMap (); //url地址和方法的映射关系,springmvc就是方法调用链 private Map urlMethodMap = new HashMap (); //Method和权限定类名映射关系, 主要是为了通过method找到该方法的对象利用反射执行 private Map methodPackageMap = new HashMap (); @Override public void init(ServletConfig config) throws ServletException { basePackage = config.getInitParameter("base-package"); try { //扫描基包得到全部的带包路径权限定名 scanBasePackage(basePackage); //把带有@Controller/@Service/@Repository的类实例化放入map中,key为注解上的名字 instance(packageNames); //Spring IOC注入 springIOC(); //完成URL地址与方法的映射关系 handleUrlMethodMap(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } } /** * 扫描基包 * @param basePackage */ private void scanBasePackage(String basePackage){ //注意为了得到基包下面的URL路径,需要对basePackage包转换,将.替换为/ URL url = this.getClass().getClassLoader().getResource(basePackage.replaceAll("\\.", "/")); File basePackageFile = new File(url.getPath()); System.out.println("scan:" + basePackageFile); File[] childFiles = basePackageFile.listFiles(); for (File file : childFiles){ if (file.isDirectory()){ scanBasePackage(basePackage + "." + file.getName()); }else if (file.isFile()){ packageNames.add(basePackage + "." + file.getName().split("\\.")[0]); } } } /** * 实例化 * @param packageNames * @throws ClassNotFoundException * @throws IllegalAccessException * @throws InstantiationException */ private void instance(List packageNames) throws ClassNotFoundException, IllegalAccessException, InstantiationException { if (packageNames.size() < 1){ return; } for (String string : packageNames){ Class c = Class.forName(string); if(c.isAnnotationPresent(Controller.class)){ Controller controller = c.getAnnotation(Controller.class); String controllerName = controller.value(); instanceMap.put(controllerName, c.newInstance()); nameMap.put(string, controllerName); System.out.println("Controller:" + string + ", value:" + controller.value()); }else if (c.isAnnotationPresent(Service.class)){ Service service = c.getAnnotation(Service.class); String serviceName = service.value(); instanceMap.put(serviceName, c.newInstance()); nameMap.put(string, serviceName); System.out.println("Service:" + string + ",value:" + service.value()); }else if (c.isAnnotationPresent(Repository.class)){ Repository repository = c.getAnnotation(Repository.class); String repositoryName = repository.value(); instanceMap.put(repositoryName, c.newInstance()); nameMap.put(string, repositoryName); System.out.println("Repository:" + string + ",value:" + repository.value()); } } } /** * 依赖注入 * @throws IllegalAccessException */ private void springIOC() throws IllegalAccessException { for (Map.Entry entry : instanceMap.entrySet()){ Field[] fields = entry.getValue().getClass().getDeclaredFields(); for (Field field : fields){ if (field.isAnnotationPresent(Qualifier.class)){ String name = field.getAnnotation(Qualifier.class).value(); field.setAccessible(true); field.set(entry.getValue(), instanceMap.get(name)); } } } } /** * url映射处理 * @throws ClassNotFoundException */ private void handleUrlMethodMap() throws ClassNotFoundException { if (packageNames.size() < 1){ return; } for (String string : packageNames){ Class c = Class.forName(string); if (c.isAnnotationPresent(Controller.class)){ Method[] methods = c.getMethods(); StringBuffer baseUrl = new StringBuffer(); if (c.isAnnotationPresent(RequestMapping.class)){ RequestMapping requestMapping = c.getAnnotation(RequestMapping.class); baseUrl.append(requestMapping.value()); } for (Method method : methods){ if (method.isAnnotationPresent(RequestMapping.class)){ RequestMapping requestMapping = method.getAnnotation(RequestMapping.class); baseUrl.append(requestMapping.value()); urlMethodMap.put(baseUrl.toString(), method); methodPackageMap.put(method, string); } } } } } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String uri = req.getRequestURI(); String contextPath = req.getContextPath(); String path = uri.replaceAll(contextPath, ""); Method method = urlMethodMap.get(path); if (method != null){ //通过method拿到controller对象,准备反射执行 String packageName = methodPackageMap.get(method); String controllerName = (String)nameMap.get(packageName); //拿到controller对象 UserController userController = (UserController)instanceMap.get(controllerName); try { method.setAccessible(true); method.invoke(userController); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }}
三、写个controller、service、dao
package com.ayo.controller;import com.ayo.annotation.Controller;import com.ayo.annotation.Qualifier;import com.ayo.annotation.RequestMapping;import com.ayo.service.UserService;@Controller("userController")@RequestMapping("/user")public class UserController { @Qualifier("userServiceImpl") private UserService userService; @RequestMapping("/insert") public void insert(){ userService.insert(); }}
package com.ayo.service;public interface UserService { public void insert();}
package com.ayo.dao;public interface UserDao { public void insert();}
参考自:微信公众号--java进阶架构师。