《架构探险》之依赖注入
写代码应该是一个由繁到简,然后由简到繁的一个螺旋上升的过程。
都说谈对象是两个人的事情,面向对象编程那也不会是一个对象的事情,而是需要处理一堆对象的依赖关系。
如果一个实例A依赖另一个实例B,最简单的做法就是在定义类Ca的时候给它定义一个类Cb的成员,初始化的时候直接new出来,这样定义Ca的时候就知道A要和B永远在一起了,这就是命中注定;如果在构造函数里面传进来,当创建A的时候就知道A要和B要在一起了,这叫指腹为婚;如果通过set方法来设置的话,这就是在合适的时候遇见合适的你~
那是不是可以在创建对象的时候不去关注如何创建对象以及对象与对象之间的关系?在定义类的时候只关注成员是什么类型就好?
如果不关注创建对象的话,那需要一个工具来负责创建对象,如果不负责成员的实例化,那只能通过工具实现对象的注入了,这个工具可以成为对象的容器,过程大致如下:
1、扫描:知道工程下都有哪些类需要负责,知道哪些属性需要注入(可以通过注解的方式标记);
2、实例化:将类实例化,通过HashMap来管理类与对象的映射关系;
3、依赖注入:根据成员属性,注入对应的实例对象。
实例化对象大概可以是这样:
public static Object newInstance(Class clazz){ Object object = clazz.newInstance(); //try catch }
依赖注入大概可以是这样:
public static void setField(Object object, field field, Object value){ field.setAccessible(true); //try catch field.set(object,value); }
在依赖注入前需要遍历属性,判断属性是否需要注入(主要是逻辑):
if(field.isAnnotationPresent(Inject.class)){ //判断是否标记,Injection是自定义注解 fieldType = field.getType(); //属性类型,据此在对象容器里寻找需要的实例注入 fieldInstance = getFieldInstance(); setField(beanInstance, field, fieldInstance); }
********************************************************************************************************************
附:依赖注入是通过Java的反射机制实现,在Web应用中MVC也是通过Java的反射机制实现的,依赖注入针对的属性,MVC针对的是方法。在传统的Servlet编程里,需要针对每个Get/Post写Servlet,量大、重复,所以可以将Servlet的实现放进框架,应用只需要实现Controller就行,Servlet根据Controller上的路径注解来实现请求转发。步骤大致如下:
1、扫描:知道有哪些Controller类
2、遍历:针对每个Controller类遍历其方法,分析注解
3、映射关系管理:管理请求方法与路径与类和方法的关系
映射关系建立的过程可以是这个样子:
Method[] methods = controllerClass.getDeclaredMethods(); for(method:methods){ method.isAnnotationPresent(Action.class){ Action action = method.getAnnotation(Action.class); String url = action.value(); ...... //分析url,封装成请求方法和路径,将类和方法封装成Handler,使用HashMap管理 } }
框架里的Servlet需要实现请求转发,所有的请求都会进入Servlet,Servlet根据请求的方法和url就可以在映射关系管理容器中找到对应的类和方法,根据在对象管理容器中可以根据类找到对应的实例化对象,然后就交给Controller了,实现了请求转发。
Servlet可以是这个样子:
Handler handler = getHandler(requestMethod, requestPath);//根据映射关系 controllerBean = getBean(handler.getControllerClass());//在对象容器中获得 Method method = handler.getActionMethod(); invokeMethod(controllderBean, method, parms)
invokeMethod可以是这个样子:
public static Object invokeMethod(Object object, Method method, Object... params){ method.setAccessible(true); //try catch Object result = method.invoke(object, params); return result; }
然后就可以在Controller里写好多东西了~