打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
浅谈Spring设计模式

原文地址

https://blog.csdn.net/Dwade_mia/article/details/78883045

工厂模式

BeanFactory,从xml或者注解加载BeanDefinition,然后实例化对象,其中AbstractAutowiredCapableBeanFactory实现了主要的逻辑

单例模式

spring创建的bean默认为singleton

适配器模式

比如说Springmvc的HandlerInterceptorAdapter就是个接口适配器,实现了AsyncHandlerInterceptor(HandlerInterceptor的子类),ThemeChangeInterceptor继承至HandlerInterceptorAdapter,只需要重写关注的方法即可,不相关的方法完全可以忽略。

public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)            throws Exception {        return true;    }    @Override    public void postHandle(            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)            throws Exception {    }    @Override    public void afterCompletion(            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)            throws Exception {    }    @Override    public void afterConcurrentHandlingStarted(            HttpServletRequest request, HttpServletResponse response, Object handler)            throws Exception {    }}public class ThemeChangeInterceptor extends HandlerInterceptorAdapter {    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)            throws ServletException {        // do somethings            }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

个人认为用得最好的地方莫过于spring-jms的MessagingMessageListenerAdapter,在onMessage中将jsm的Message转换为message模块的Message对象(内部类的LazyResolutionMessage,重写了getPayload、getHeader),并交给message模块的InvocableHandleMethod,这样一来便可以实现jms与spring message无缝适配对接了,在spring-websocket也是相同的套路

public class MessagingMessageListenerAdapter extends AbstractAdaptableMessageListener {    private InvocableHandlerMethod handlerMethod;    public void setHandlerMethod(InvocableHandlerMethod handlerMethod) {        this.handlerMethod = handlerMethod;    }    @Override    public void onMessage(javax.jms.Message jmsMessage, Session session) throws JMSException {        Message<?> message = toMessagingMessage(jmsMessage);        if (logger.isDebugEnabled()) {            logger.debug("Processing [" + message + "]");        }        Object result = invokeHandler(jmsMessage, session, message);        if (result != null) {            handleResult(result, jmsMessage, session);        }        else {            logger.trace("No result object given - no result to handle");        }    }    protected Message<?> toMessagingMessage(javax.jms.Message jmsMessage) {        try {            return (Message<?>) getMessagingMessageConverter().fromMessage(jmsMessage);        }        catch (JMSException ex) {            throw new MessageConversionException("Could not convert JMS message", ex);        }    }    // 忽略部分代码}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

装饰模式

装饰模式是指在不影响其它类的情况下,动态透明的扩展一个对象的功能,比如TransactionAwareCacheDecorator增加了对事务的支持,在事务提交、回滚的时候分别对Cache的数据进行处理。不过,装饰模式和静态代理还是有区别的,装饰模式只是在调用前后加了些逻辑,但是最终还是需要调用父类或者装饰类;而代理模式是需要or不需要来完成对代理方法的调用,比如AOP可以有选择性地处理某些方法,并不一定会执行代理类的具体方法。

public class TransactionAwareCacheDecorator implements Cache {    private final Cache targetCache;    @Override    public void put(final Object key, final Object value) {        if (TransactionSynchronizationManager.isSynchronizationActive()) {            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {                @Override                public void afterCommit() {                    targetCache.put(key, value);                }            });        }        else {            this.targetCache.put(key, value);        }    }    // 忽略部分代码}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

观察者模式

在spring中我们借助ApplicationListener、ApplicationEventPublisher便可以完成简直的事件通知。当调用ApplicationEventPublisher#publishEvent()时,spring会查找实现了ApplicationListener接口、并且使用了指定泛型的bean,然后调用其onApplicationEvent。下面的代码示范了spring发出ContextRefreshedEvent事件。

ApplicationEventPublisher eventPublisher = xxx;eventPublisher.publishEvent( new ContextRefreshedEvent( applicationContext ) );public class TestListener implements ApplicationListener<ContextRefreshedEvent> {    @Override    public void onApplicationEvent(ContextRefreshedEvent event) {        // invoke after spring context refreshed    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

策略模式

比如SpringMVC的HandlerMethodArgumentResolver接口,使用HandlerMethodArgumentResolverComposite(实现HandlerMethodArgumentResolver接口),通过遍历内部所有的HandlerMethodArgumentResolver(当然有缓存 机制),选择support返回true的实例,并把接口的调用交给该实例处理

其实,我们在写业务代码的时候,很多童鞋喜欢用Map保存策略实现类,其实这样并不好,不够灵活,应该像spring这样提供一个support方法,可以支持更加复杂的逻辑判断

public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {    protected final Log logger = LogFactory.getLog(getClass());    private final List<HandlerMethodArgumentResolver> argumentResolvers =            new LinkedList<HandlerMethodArgumentResolver>();    private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache =            new ConcurrentHashMap<MethodParameter, HandlerMethodArgumentResolver>(256);    @Override    public boolean supportsParameter(MethodParameter parameter) {        return (getArgumentResolver(parameter) != null);    }    private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {        HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);        if (result == null) {            for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {                if (methodArgumentResolver.supportsParameter(parameter)) {                    result = methodArgumentResolver;                    this.argumentResolverCache.put(parameter, result);                    break;                }            }        }        return result;    }    @Override    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,            NativeWebRequest webRequest, 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);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

代理模式

静态代理在Spring websocket里面非常常见,比如说WebsocketHandlerDecorator,因为它不方便直接操作开发者自定义的WebSocketHandler,因此使用了代理模式。另外,cglib、jdk动态代理在spring中也是非常常见

public class WebSocketHandlerDecorator implements WebSocketHandler {    private final WebSocketHandler delegate;    public WebSocketHandlerDecorator(WebSocketHandler delegate) {        Assert.notNull(delegate, "Delegate must not be null");        this.delegate = delegate;    }    @Override    public void afterConnectionEstablished(WebSocketSession session) throws Exception {        this.delegate.afterConnectionEstablished(session);    }    @Override    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {        this.delegate.handleMessage(session, message);    }    // 省略部分代码}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

责任链模式

比如SpringMVC的HandlerExecutionChain与HandlerInterceptor,以及ExceptionHandlerResolver

下面是HandlerExecutionChain的部分代码,由DispatcherServlet调用,内部维护了interceptorIndex,用于标记当前调用HandlerInterceptor的位置

public class HandlerExecutionChain {    private final Object handler;    private HandlerInterceptor[] interceptors;    private int interceptorIndex = -1;    boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {        HandlerInterceptor[] interceptors = getInterceptors();        if (!ObjectUtils.isEmpty(interceptors)) {            for (int i = 0; i < interceptors.length; i++) {                HandlerInterceptor interceptor = interceptors[i];                if (!interceptor.preHandle(request, response, this.handler)) {                    triggerAfterCompletion(request, response, null);                    return false;                }                this.interceptorIndex = i;            }        }        return true;    }    void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {        HandlerInterceptor[] interceptors = getInterceptors();        if (!ObjectUtils.isEmpty(interceptors)) {            for (int i = interceptors.length - 1; i >= 0; i--) {                HandlerInterceptor interceptor = interceptors[i];                interceptor.postHandle(request, response, this.handler, mv);            }        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

再比如说springMVC对异常的处理,DispatcherServlet会保存所有的HandlerExceptionResolver,当出现异常时,挨个调用HandlerExceptionResolver实例的resolveException方法,直到返回ModelAndView

建设者模式(Builder)

为了简化对象的创建过程而使用的一种设计模式,比如BeanDefinitionBuilder是为了简化BeanDefinition的创建过程,每次setXXX都会返回BeanDefinitionBuilder实例,方便以链条编码的方式创建BeanDefinitionBuilder

public class BeanDefinitionBuilder {    public static BeanDefinitionBuilder genericBeanDefinition(Class<?> beanClass) {        BeanDefinitionBuilder builder = new BeanDefinitionBuilder();        builder.beanDefinition = new GenericBeanDefinition();        builder.beanDefinition.setBeanClass(beanClass);        return builder;    }    private AbstractBeanDefinition beanDefinition;    public BeanDefinitionBuilder addConstructorArgValue(Object value) {        this.beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(                this.constructorArgIndex++, value);        return this;    }    public BeanDefinitionBuilder addPropertyValue(String name, Object value) {        this.beanDefinition.getPropertyValues().add(name, value);        return this;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

模板模式

spring中很多地方会这样做,在一个方法里面完成了一小部分逻辑,然后接着调用一个或多个抽象方法,而这个抽象方法需要由子类重写,比如AbstractApplicationContext里面的refresh()、getBeanFactory()等等,这样便可以很好的提高了程序的扩展性

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
SpringMVC源码总结(九)HandlerMethodArgumentResolver介绍
Spring MVC
过滤器 和 拦截器的 6个区别,别再傻傻分不清了
spring mvc 拦截器
java设计模式基础--拦截器
我在项目内使用了设计模式后,同事直呼看不懂
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服