相关设计模式
- 适配器模式
- 模板方法模式
- 策略模式
- 组合模式
- 代理模式(使用Cglib的动态代理)
适配器模式
旧的类无法被删除和修改,在新的方法中对其进行方法的调用和前后进行操作
继承方式
//被适配的类public class AdapterClass{public void handleMethod(){System.out.println("this is method to be handled")}}//适配器接口public interface Adapter{void handle();}//适配器实现类public class AdapterImpl extends AdapterClass implements Adapter{@Overridepublic void handle(){super.handleMethod();}}//测试类public class Test{public static void main(Stirng[] args){Adapter adapter = new AdapterImpl();adapter.handle();}}
组合方式
//被适配的类public class AdapterClass{public void handleMethod(){System.out.println("this is method to be handled")}}//适配器接口public interface Adapter{void handle();}//适配器实现类public class AdapterImpl implements Adapter{private AdapterClass adapterClass;public AdapterImpl(AdapterClass adapterClass){this.adapterClass = adapterClass;}@Overridepublic void handle(){this.adapterClass.handleMethod();}}//测试类public class Test{public static void main(Stirng[] args){AdapterClass adapterClass = new AdapterClass();Adapter adapter = new AdapterImpl(adapterClass);adapter.handle();}}
模板方法模式
模板方法的构成
- 抽象的基类以及其中定义的若干个抽象方法和一个final方法
- 定义为final是为了不让子类复写方法,改变实现逻辑
- 实现了抽象基类的具体的类,完成对抽象方法的实现
//抽象基类public abstract class AbstractDatabaseExcecutor{abstract void openConnection();abstract String getResultSet();abstract void closeConnection();//为什么要定义为final是为了不让子类复写方法,改变实现逻辑public final void execute(){openConnection();getResultSet();closeConnection();}}//具体实现类1public class MysqlDatabaseExcutor extends AbstractDatabaseExcecuto{@Overridevoid openConnection(){System.out.println("mysql open conneciton")}@OverrideString getResultSet(){System.out.println("mysql result set")}@Overridevoid closeConnection(){System.out.println("mysql close connection")}}//具体实现类2public class OracleDatabaseExcutor extends AbstractDatabaseExcecuto{@Overridevoid openConnection(){System.out.println("oracle open conneciton")}@OverrideString getResultSet(){System.out.println("oracle result set")}@Overridevoid closeConnection(){System.out.println("oracle close connection")}}//测试类public class Test{public static void main(Stirng[] args){AbstractDatabaseExcecuto excutor = new MysqkDatabaseExcutor();excutor.execute();excutor = new OracleDatabaseExcutor();excutor.execute();}}
策略模式
有一个抽象的接口,这个接口只定义了一个模型,不提供具体的实现,不同实现类有不同的实现
//抽象类public interface AbstractStrategy{int calc(int x, int y);}//加法实现类public class AddStrategy implements AbstractStrategy{@Overridepublic int calc(int x, int y){return x + y;}}//减法实现类public class MinusStrategy implements AbstractStratgy{@Overridepublic int calc(int x, int y){return x - y;}}//乘法实现类public class MultiStrategy implements AbstractStrategy{@Overridepublic int calc(int x, int y){return x * y;}}//环境类public class Context{private AbstractStrategy abstractStrategy;public Context(AbstractStrategy abstractStrategy){this.abstractStrategy = abstractStrategy;}public void excecute(int x, int y){int calc = this.abstractStrategy.calc(x,y);System.out.println(calc);}}//测试类public class test{public static void main(Stirng[] args){Context context = new Context(new AddStrategy());context.excute(10,20);Context context = new Context(new MinusStrategy());context.excute(10,20);Context context = new Context(new MultiStrategy());context.excute(10,20);}}
组合模式
有一个篮子,篮子里承装任意多的对象,要把篮子里的任意对象遍历出来
public abstract class Component{private String name;public String getName(){return name;}public Component(String name){this.name = name;}//protectedprotected abstract void dispaly();}
public class Product extends Component{public Product(String name){super(name);}@Overrideprotected void display(){System.out.println("the name of product is"+ this.getName());}}
public class Box extends Componnet{private List<Component> productList = new ArrayList<>();public void addProduct(Component component){this.product.add(component);}public void removeProduct(Component component){this.product.remove(component);}public Box(String name){super(name);}@Overrideprotected void display(){for(Component component : productList){component.display();}}}
//手推车里放入了商品,打印手推车中的商品public class client{public static void main(String[] args){Box box = new Box("小推车");Component c1 = new Product("牙膏");Component c2 = new Product("肥皂");Component c3 = new Product("牙刷");box.addProcuct(c1);box.addProcuct(c2);box.addProcuct(c3);box.display();}}
代理模式(JDK动态代理、Cglib的动态代理)
代理某个类,在它的方法实现前后进行一些操作(增强) 包括动态代理和静态代理
动态代理:
c JDK动态代理
public interface Target{void handle();}
public class TargetImpl implements Target{@Overridepublic void handle(){System.out.println("I can handle something");}}
/**代理类**/public class TargetHandler implements InvocatioinHandler{//被代理的类private Object target;public TargetHandler(Object target){this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable{//方法前面操作Object invoke = method.invoke(target,args);//方法后面操作return invoke;}}
public class Client{public static void main(String[] args){Target target = new TargetImpl();InvocatioinHandler handler = new TargetHandler(target);//代理对象 对象名{$Proxy0@502},非真实对象Target o = Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getIntefaces(),handler)o.handle();}}
Cglib动态代理
public class User{public void userMethod(){System.out.println("I am a user");}}
//选择使用spring中的cgblibpublic class UserMethodIntercepter implements MethodIntercepter{@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy){return methodProxy.invokeSuper(0,objects);}}
public class Client{public static void main(String[] args){//spring的,proxy.EnhancerEnhancer enhancer = new Enhancer();//让其继承一个类enhancer.setSuperclass(User.class);enhancer.setCallbacek(new UserMethodIntercepter());User u = (User)enhancer.create();user.userMethod();}}
两种代理的区别
JDK要实现一个接口,CGLIB不要求实现一个接口,但是由于要生成一个子类,所以类不能被fianl修饰
反射相关API讲解
public class Student{private void sayHello(String name){System.out.println("hello" + name);}}
public class Client{public static void main(String[] args) throws NoSuchMethodException{Student student= new Student();Class<?> clazz = Student.class;Method method = clazz.getDeclareMehod("sayHello",String.calss);//设置允许method.setAccessibale(true);//参数数组String[] strings = new String[]{"zhangsan"};method.invoke(student,strings);}}//如果将整个main方法移入到student类中,那么无需设置axxessibale就可以访问,因为main本身就在Student类中
分析SpringMvc中重要的类和组件
基于HttpServlet的API的一层封装
- FrameworkServlet
- DispatcherServlet
- HandlerInterceptor
- HandlerInteceptorAdapter
- HandlerMapping
- HandlerMethod
- HandlerAdapter
- MethodParameter
- HandlerMethodArgumentResolver
- HandlerMethodArgumentResolverComposite
- RequestResponseBodyMethodProcessor
FrameworkServlet
//处理web请求的一般过程是继承HttpServlet然后实现其中的doPost(post请求)和doGet方法(get请求)public abstract class HttpServlet extends GenericServlet{....}//查找实现了doGet方法的类,ctrl+T,找到了FrameworkServlet//它继承了HttpServlet实现了doGet方法,它在springframework.web.servlet包中,请求就正式转入了spring的控制
DispatcherServlet
//也在org.springframework.web.servlet中,根据请求找到处理请求的组件(controller)//提供便捷的映射和异常处理的公共组件
HandlerInterceptor
拦截器顶层的实现接口,对请求的若干个阶段进行拦截
//jdk1.8之后的default关键字,实现此接口可以不用实现所有的方法public interface HandlerInterceptor {//请求开始之前default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {return true;}//请求结束之后,画面渲染之前default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {}//画面渲染之后(有的时候画面不存在,如modelAndView为空的情况)default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {}}
HandlerInterceptorAdapter
此类的作用,如果直接实现HandlerInterceptor就要重写所有方法,实现HandlerInterceptorAdapter方法不需要重写所有方法,JDK1.8的default关键字已实现,作用变为了兼容一些老接口
public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {}@Overridepublic void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {}}public interface AsyncHandlerInterceptor extends HandlerInterceptor {/*** Called instead of {@code postHandle} and {@code afterCompletion}, when* the a handler is being executed concurrently.* <p>Implementations may use the provided request and response but should* avoid modifying them in ways that would conflict with the concurrent* execution of the handler. A typical use of this method would be to* clean up thread-local variables.*/void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception;}
HandlerMappping
处理请求到处理器的映射的作用,处理@RequestMapping等注解的方法/类与请求URL的映射 接口
//MatchableHandlerMapping繼承了HandlerMappping接口public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappingimplements MatchableHandlerMapping, EmbeddedValueResolverAware {....}
HandlerMethod
可以理解为RequestMappingHandlerMapping映射出的方法,即类似@RequestMapping注解的方法 方法的元信息
HandlerAdapter
适配器模式,为什么是适配器模式,这个adapter判断是通过继承controller方法进行的处理 还是通过注解的方式
//在直接大量出现之前都是要实现该接口,重写该方法@FunctionalInterfa cepublic interface Controller {@NullableModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;}
MethodParameter
封装了注解了@RequstMapping的方法的请求参数,请求参数的注解
HandlerMethodArgumentResolver
对请求参数进行处理
public interface HandlerMethodArgumentResolver {//判断传入的MethodParameter是否能够被当前的HandlerMethodArgumentResolver执行//eg:PathvariableMapMethodArgumentResolverboolean supportsParameter(MethodParameter parameter);//supportsParameter返回为true时调用该方法,同时将请求参数转到参数中@NullableObject resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;}
HandlerMethodArgumentResolverComposite
使用了组合设计模式,组合了HandlerMethodArgumentResolver,封装了HandlerMethodArgumentResolver一系列的实现器,方便用来方便遍历解析器集合,可以理解为一个HandlerMethodArgumentResolver的容器
public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {protected final Log logger = LogFactory.getLog(getClass());private final List<HandlerMethodArgumentResolver> argumentResolvers = new LinkedList<>();private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache =new ConcurrentHashMap<>(256);/*** Add the given {@link HandlerMethodArgumentResolver}.*/public HandlerMethodArgumentResolverComposite addResolver(HandlerMethodArgumentResolver resolver) {this.argumentResolvers.add(resolver);return this;}/*** Add the given {@link HandlerMethodArgumentResolver}s.* @since 4.3*/public HandlerMethodArgumentResolverComposite addResolvers(@Nullable HandlerMethodArgumentResolver... resolvers) {if (resolvers != null) {for (HandlerMethodArgumentResolver resolver : resolvers) {this.argumentResolvers.add(resolver);}}return this;}/*** Add the given {@link HandlerMethodArgumentResolver}s.*/public HandlerMethodArgumentResolverComposite addResolvers(@Nullable List<? extends HandlerMethodArgumentResolver> resolvers) {if (resolvers != null) {for (HandlerMethodArgumentResolver resolver : resolvers) {this.argumentResolvers.add(resolver);}}return this;}/*** Return a read-only list with the contained resolvers, or an empty list.*/public List<HandlerMethodArgumentResolver> getResolvers() {return Collections.unmodifiableList(this.argumentResolvers);}/*** Clear the list of configured resolvers.* @since 4.3*/public void clear() {this.argumentResolvers.clear();}/*** Whether the given {@linkplain MethodParameter method parameter} is supported by any registered* {@link HandlerMethodArgumentResolver}.*/@Overridepublic boolean supportsParameter(MethodParameter parameter) {return (getArgumentResolver(parameter) != null);}/*** Iterate over registered {@link HandlerMethodArgumentResolver}s and invoke the one that supports it.* @throws IllegalStateException if no suitable {@link HandlerMethodArgumentResolver} is found.*/@Override@Nullablepublic Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);if (resolver == null) {throw new IllegalArgumentException("Unknown parameter type [" + parameter.getParameterType().getName() + "]");}return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);}/*** Find a registered {@link HandlerMethodArgumentResolver} that supports the given method parameter.*/@Nullableprivate HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);if (result == null) {for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {if (logger.isTraceEnabled()) {logger.trace("Testing if argument resolver [" + methodArgumentResolver + "] supports [" +parameter.getGenericParameterType() + "]");}if (methodArgumentResolver.supportsParameter(parameter)) {result = methodArgumentResolver;this.argumentResolverCache.put(parameter, result);break;}}}return result;}}
RequestResponseBodyMethodProcessor
@RequestBody和@ResponseBody处理
//最上层实现了HandlerMethodArgumentResolver,是用来处理@RequestBody类的请求//supportsReturnType和handleReturnValue是处理返回值的public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor {/*** Basic constructor with converters only. Suitable for resolving* {@code @RequestBody}. For handling {@code @ResponseBody} consider also* providing a {@code ContentNegotiationManager}.*/public RequestResponseBodyMethodProcessor(List<HttpMessageConverter<?>> converters) {super(converters);}/*** Basic constructor with converters and {@code ContentNegotiationManager}.* Suitable for resolving {@code @RequestBody} and handling* {@code @ResponseBody} without {@code Request~} or* {@code ResponseBodyAdvice}.*/public RequestResponseBodyMethodProcessor(List<HttpMessageConverter<?>> converters,@Nullable ContentNegotiationManager manager) {super(converters, manager);}/*** Complete constructor for resolving {@code @RequestBody} method arguments.* For handling {@code @ResponseBody} consider also providing a* {@code ContentNegotiationManager}.* @since 4.2*/public RequestResponseBodyMethodProcessor(List<HttpMessageConverter<?>> converters,@Nullable List<Object> requestResponseBodyAdvice) {super(converters, null, requestResponseBodyAdvice);}/*** Complete constructor for resolving {@code @RequestBody} and handling* {@code @ResponseBody}.*/public RequestResponseBodyMethodProcessor(List<HttpMessageConverter<?>> converters,@Nullable ContentNegotiationManager manager, @Nullable List<Object> requestResponseBodyAdvice) {super(converters, manager, requestResponseBodyAdvice);}@Overridepublic boolean supportsParameter(MethodParameter parameter) {return parameter.hasParameterAnnotation(RequestBody.class);}@Overridepublic boolean supportsReturnType(MethodParameter returnType) {return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||returnType.hasMethodAnnotation(ResponseBody.class));}/*** Throws MethodArgumentNotValidException if validation fails.* @throws HttpMessageNotReadableException if {@link RequestBody#required()}* is {@code true} and there is no body content or if there is no suitable* converter to read the content with.*/@Overridepublic Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {parameter = parameter.nestedIfOptional();Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());String name = Conventions.getVariableNameForParameter(parameter);if (binderFactory != null) {WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);if (arg != null) {validateIfApplicable(binder, parameter);if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());}}if (mavContainer != null) {mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());}}return adaptArgumentIfNecessary(arg, parameter);}@Overrideprotected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter parameter,Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);Assert.state(servletRequest != null, "No HttpServletRequest");ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);Object arg = readWithMessageConverters(inputMessage, parameter, paramType);if (arg == null && checkRequired(parameter)) {throw new HttpMessageNotReadableException("Required request body is missing: " +parameter.getExecutable().toGenericString());}return arg;}protected boolean checkRequired(MethodParameter parameter) {RequestBody requestBody = parameter.getParameterAnnotation(RequestBody.class);return (requestBody != null && requestBody.required() && !parameter.isOptional());}@Overridepublic void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,ModelAndViewContainer mavContainer, NativeWebRequest webRequest)throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {mavContainer.setRequestHandled(true);ServletServerHttpRequest inputMessage = createInputMessage(webRequest);ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);//写回数据,java对象-> Json对象 -> 返回客户端// Try even with null return value. ResponseBodyAdvice could get involved.writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);}}
分析SpringMVC运行流程
//model@Datapublic class User{private String firstName;private String lastName;}@RestCotroller@RequestMapping(value ="/user",method = RequestMethod.GET)public class UserController{@GetMapping("/info/{firstName}/{lastName}")public User getUser(@PathVariable("firstName") String firstName,@PathVariable("lastName") String lastName){User user = new User(firstName,lastName);System.out.println(user);return user;}}
- 如果把getUser的方法设置为private也是可以的,使用的springMvc的反射
源码分析
- User user = new User(firstName,lastName); 处打断点
- HttpServlet的继承类-> FrameworkServlet的doGet方法 -> processRequest(..)
- -> doService(..)抽象类使用了模板方法 -> 子类DispatcherServlet的doService(..)方法
- -> doDispatch(..)处理handlerMapping和handlerAdapter的方法
详解doDispatch(..)
