对于Service的自动注入
一. 前言
在前上一章教程中,我们实现了简单的Web框架。
本章将在上一章的基础上,进一步扩展程序。
注:
1.本文针对初学Java的同学训练学习思路,请不要太纠结于细节问题。
2.本文旨在达到抛砖引玉的效果,希望大家扩展本例子,以学到更多知识的精髓。
学习本章需要准备的知识:
1.读完本系列教程的前面章节。
二. 步入正题
话不多说,大家自己理解,下面步入正题:
我们来实现Service的自动注入。
我们希望把Servcie获得的代码做如下修改:
修改前:
修改后:
这样减少了框架对业务代码的侵入。
首先修改PersonController如下:
1 /** 2 * 3 * @author http://www.java123.vip 4 * 5 */ 6 @Controller 7 public class PersonController { 8 9 @Autowired 10 public PersonService personService; 11 12 @Request(path="/person.do") 13 public String query(@Parameter(name="personid")String personId) { 14 15 Person personResult = personService.getPerson(personId); 16 17 StringBuffer result = new StringBuffer(); 18 result.append("id:"+personResult.id); 19 result.append("<br/>username:"+personResult.username); 20 result.append("<br/>password:"+personResult.passwd); 21 22 return result.toString(); 23 } 24 25 }
制作如下两个注解:
1 /** 2 * 3 * @author http://www.java123.vip 4 * 5 */ 6 @Target(value = { ElementType.FIELD }) 7 @Retention(value = RetentionPolicy.RUNTIME) 8 public @interface Autowired { 9 10 }
1 /** 2 * 3 * @author http://www.java123.vip 4 * 5 */ 6 @Target(value = { ElementType.TYPE }) 7 @Retention(value = RetentionPolicy.RUNTIME) 8 public @interface Service { 9 10 }
修改PersonService代码如下:
1 /** 2 * 3 * @author http://www.java123.vip 4 * 5 */ 6 @Service 7 public class PersonService { 8 9 @Autowired 10 public PersonDao personDao; 11 12 public Person getPerson(String personid) { 13 14 15 Person person = personDao.getPersonById(personid); 16 17 return person; 18 } 19 }
修改DispacherServlet代码如下:
1 /** 2 * 3 * @author http://www.java123.vip 4 * 5 */ 6 public class DispacherServlet extends HttpServlet{ 7 8 private Map<String,ControllerInvoker> controllerMap = new HashMap<String,ControllerInvoker>(); 9 10 public DispacherServlet() { 11 12 String controllerPackage = "vip.java123.fileview.app.web"; 13 String servicePackage = "vip.java123.fileview.app.service"; 14 15 MyContainer container = MyContainer.getInstance(); 16 17 try { 18 // load all service 19 // 扫描service包下面的所有类,创建实例并对@Autowired注解属性注入实例 20 Class[] serviceClasses = ClassScaner.getClasses(servicePackage); 21 for(int i = 0; i < serviceClasses.length; i ++) { 22 Class serviceClass = serviceClasses[i]; 23 24 // 生成实例 25 Object serviceObj = container.getObject(serviceClass); 26 27 // 处理@Autowired注解属性 28 Field[] fields = serviceClass.getFields(); 29 for(int j = 0; j < fields.length; j++) { 30 Field field = fields[j]; 31 if(field.getAnnotation(Autowired.class) != null) { 32 Class autowiredClass = field.getType(); 33 34 // 对@Autowired注入实例 35 Object autowiredObj = container.getObject(autowiredClass); 36 field.set(serviceObj, autowiredObj); 37 } 38 } 39 40 } 41 42 43 // load all controller 44 // 扫描controller包下面的所有类,并加载包含注解@Controller的类 45 Class[] controllerClasses = ClassScaner.getClasses(controllerPackage); 46 for(int i = 0; i < controllerClasses.length; i ++) { 47 Class controllerClass = controllerClasses[i]; 48 49 // 判断是否含有注解@Controller 50 if(controllerClass.getAnnotation(Controller.class) != null) { 51 52 // 生成新的Controller实例 53 Object controllerObj = controllerClass.newInstance(); 54 55 // 处理@Autowired注解属性 56 Field[] fields = controllerClass.getFields(); 57 for(int j = 0; j < fields.length; j++) { 58 Field field = fields[j]; 59 if(field.getAnnotation(Autowired.class) != null) { 60 Class autowiredClass = field.getType(); 61 // 对@Autowired注入实例 62 Object autowiredObj = container.getObject(autowiredClass); 63 field.set(controllerObj, autowiredObj); 64 } 65 } 66 67 // 扫描所有的方法 68 Method[] methods = controllerClass.getMethods(); 69 for(int j = 0; j < methods.length; j ++) { 70 Method method = methods[j]; 71 72 // 加载含有@Request注解的方法 73 Request requestAnnotation = method.getAnnotation(Request.class); 74 if(requestAnnotation != null) { 75 76 // 注解声明的请求路径 77 String path = requestAnnotation.path(); 78 79 // 做一个invoker,以便请求过来时调用 80 ControllerInvoker invoker = new ControllerInvoker(); 81 invoker.path = path; 82 invoker.obj = controllerObj; 83 invoker.method = method; 84 85 // 处理@Parameter注解 86 List<String> parameterNameList = new ArrayList<String>(); 87 Annotation[][] annotations = method.getParameterAnnotations(); 88 for(int k = 0; k < annotations.length; k ++) { 89 if(annotations[k].length > 0) { 90 Parameter parameterAnnotaion = (Parameter)annotations[k][0]; 91 String parameterName = parameterAnnotaion.name(); 92 parameterNameList.add(parameterName); 93 } 94 } 95 invoker.paramNames = new String[parameterNameList.size()]; 96 for(int m = 0; m < parameterNameList.size(); m ++) { 97 invoker.paramNames[m] = parameterNameList.get(m); 98 } 99 100 // 将做好的invoker放入Map中,key为请求路径 101 System.out.println("load controller:"+path); 102 controllerMap.put(path, invoker); 103 } 104 } 105 } 106 } 107 108 } catch (ClassNotFoundException e) { 109 e.printStackTrace(); 110 } catch (IOException e) { 111 e.printStackTrace(); 112 } catch (InstantiationException e) { 113 e.printStackTrace(); 114 } catch (IllegalAccessException e) { 115 e.printStackTrace(); 116 } 117 118 } 119 120 121 /** 122 * 处理Get请求 123 */ 124 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 125 // 获得请求路径 126 String contextPath = request.getContextPath(); 127 String requestPath = request.getRequestURI(); 128 String path = requestPath.replace(contextPath, ""); 129 130 System.out.println("request:"+path); 131 132 // 根据请求路径获得做好的invoker 133 ControllerInvoker invoker = controllerMap.get(path); 134 135 if(invoker != null) { 136 // 根据请求的参数值设置invoker 137 invoker.paramValues = new String[invoker.paramNames.length]; 138 for(int i = 0; i < invoker.paramNames.length; i ++) { 139 invoker.paramValues[i] = request.getParameter(invoker.paramNames[i]); 140 } 141 142 // 调用invoker,并将结果写到response中 143 String result = invoker.invokMethod(); 144 response.getWriter().println(result); 145 } 146 } 147 148 }
三. 测试
启动服务器:
向服务器请求person.html文件,在浏览器端输入1,点query按钮:
显示查询结果:
完整程序请大家从[这里]下载
如有问题,大家来我的网站进行提问。
https://www.java123.vip/qa
版权声明:本教程版权归java123.vip所有,禁止任何形式的转载与引用。