作者:杨秀丽
推荐理由:很好的诠释了Java的设计模式思想,在实际的开发过程中当中很实用,也是一个程序员所必须具备的基本技能。
转至元数据起始
1.工厂设计模式
Spring使用工厂模式可以通过BeanFactory或ApplicationContext创建bean对象。
二者对比:
BeanFactory :延迟注入(使用到某个 bean 的时候才会注入),相比于BeanFactory来说会占用更少的内存,程序启动速度更快。
ApplicationContext :容器启动的时候,不管你用没用到,一次性创建所有 bean 。BeanFactory 仅提供了最基本的依赖注入支持,ApplicationContext 扩展了 BeanFactory ,除了有BeanFactory的功能还有额外更多功能,所以一般开发人员使用ApplicationContext会更多。
2. 单例设计模式
Spring中bean的默认作用域就是singleton。
Spring实现单例的方式:
xml格式:
注解:@Scope(value = “singleton”)
3.动态代理模式
Spring 实现 Aop 使用了动态代理模式。
先看看 Spring 如何实现代理类的,要实现代理类在 Spring 的配置文件中通常是这样定一个 Bean 的,如下:
配置代理类 Bean
<bean id="testBeanSingleton"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>
org.springframework.aop.framework.PrototypeTargetTests$TestBean
</value>
</property>
<property name="target"><ref local="testBeanTarget"></ref> </property>
<property name="singleton"><value>true</value></property>
<property name="interceptorNames">
<list>
<value>testInterceptor</value>
<value>testInterceptor2</value>
</list>
</property>
</bean>
配置上看到要设置被代理的接口,和接口的实现类也就是目标类,以及拦截器也就在执行目标方法之前被调用,这里 Spring 中定义的各种各样的拦截器,可以选择使用。
下面看看 Spring 如何完成了代理以及是如何调用拦截器的。
前面提到 Spring Aop 也是实现其自身的扩展点来完成这个特性的,从这个代理类可以看出它正是继承了 FactoryBean 的 ProxyFactoryBean,FactoryBean 之所以特别就在于它可以让你自定义对象的创建方法。当然代理对象要通过 Proxy 类来动态生成。
下面是 Spring 创建的代理对象的时序图:
Spring 创建了代理对象后,当你调用目标对象上的方法时,将都会被代理到 InvocationHandler 类的 invoke 方法中执行,这在前面已经解释。在这里 JdkDynamicAopProxy 类实现了 InvocationHandler 接口。
下面再看看 Spring 是如何调用拦截器的,下面是这个过程的时序图:
以上所说的都是 Jdk 动态代理,Spring 还支持一种 CGLIB 类代理,这里不讨论。
- 适配器模式
实现方式:SpringMVC中的适配器HandlerAdatper。
实现原理:HandlerAdatper根据Handler规则执行不同的Handler。
实现过程:
DispatcherServlet根据HandlerMapping返回的handler,向HandlerAdatper发起请求,处理Handler。HandlerAdapter根据规则找到对应的Handler并让其执行,执行完毕后Handler会向HandlerAdapter返回一个ModelAndView,最后由HandlerAdapter向DispatchServelet返回一个ModelAndView。
实现意义:
HandlerAdatper使得Handler的扩展变得容易,只需要增加一个新的Handler和一个对应的HandlerAdapter即可。因此Spring定义了一个适配接口,使得每一种Controller有一种对应的适配器实现类,让适配器代替controller执行相应的方法。这样在扩展Controller时,只需要增加一个适配器类就完成了SpringMVC的扩展了。 - 策略模式
Spring 中策略模式使用有多个地方,如 Bean 定义对象的创建以及代理对象的创建等。这里主要看一下代理对象创建的策略模式的实现。
前面已经了解 Spring 的代理方式有两个 Jdk 动态代理和 CGLIB 代理。这两个代理方式的使用正是使用了策略模式。它的结构图如下所示:
Spring 中策略模式结构图
在上面结构图中与标准的策略模式结构稍微有点不同,这里抽象策略是 AopProxy 接口,Cglib2AopProxy 和 JdkDynamicAopProxy 分别代表两种策略的实现方式,ProxyFactoryBean 就是代表 Context 角色,它根据条件选择使用 Jdk 代理方式还是 CGLIB 方式。
config.isOptimize()和config.isProxyTargetClass()都默认false,然后判断targetClass是否为接口。
如果目标对象实现了接口,默认采用JDK动态代理;如果目标对象没有实现接口,则采用Cglib动态代理。