在JDK里的一些应用,我们打开一个类,XmlAdapter,我们看一下这个名字就可以很充分的说明他是一个Adapter,
那这个类是JAXB包下的,
public abstract class XmlAdapter<ValueType,BoundType>
package javax.xml.bind.annotation.adapters;
在JDK中处理XML序列化和反序列化使用的,那这里面一个构造器
protected XmlAdapter() {}
还有两个方法
public abstract BoundType unmarshal(ValueType v) throws Exception;
public abstract ValueType marshal(BoundType v) throws Exception;
public @interface XmlJavaTypeAdapter
很明显这个是一个注解,那我们在使用XML序列化的时候,也经常使用XML里面的注解,另外我们看一下他的包,
我们看到annotation下有一个adapters,那这里是一个适配器的注解,我们怎么使用呢,例如我们在做序列化和反序列化的时候,
对于时间类型我们自己可以写一个类,同时继承这个抽象类,然后实现unmarshal这个反序列化方法,同时再实现marshal序列化
方法,我们只要实现自定义的适配器就可以了,那在Spring中使用适配器也使用的非常广泛,那我们先看一下Spring中的使用AOP的
一个案例,打开AdvisorAdapter,我们看到这个包在aop下边
很明显每一个Advisor中的advise都要适配成对应的MethodInterceptor对象,那我们看一下AdvisorAdaptor是一个接口,
我们看一下他的实现,我们就看一下MethodBeforeAdviceAdapter
通过这个名字就可以很明显的看出来
这个类是做什么的,也就是做增强方法,运行之前的Adapter,supportAdvise return什么呢,这个advice是不是MethodBeforeAdvice,
对他的类型进行一个判断,然后看下边getInterceptor,那在Spring的JPA中,也大量的使用了适配器模式,我们可以访问Spring的
官网,https://spring.io/projects/spring-data-jpa,我们把这个jar包拿过来
https://github.com/spring-projects/spring-data-examples/blob/master/jpa/pom.xml
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.0.9.RELEASE</version>
</dependency>
我们看一下JpaVendorAdapter,在Spring的ORM中,对于JPA的支持呢,也是采用了适配器的方式,我们看一下,首先JpaVendorAdapter,
是一个接口,我们看一下他的子类也就是他的实现类,有哪些,我们看到有一个抽象的JpaVendorAdapter
还有EclipseLink,还有HibernateJapVendorAdapter,这几个方法可以看一下,里面的英文注释,
/**
* Return the vendor-specific persistence provider.
*/
PersistenceProvider getPersistenceProvider();
返回一个具体的持久层提供者,下面看这个名字
/**
* Return the name of the persistence provider's root package
* (e.g. "oracle.toplink.essentials"). Will be used for
* excluding provider classes from temporary class overriding.
* @since 2.5.2
*/
@Nullable
default String getPersistenceProviderRootPackage() {
return null;
}
RootPackage,很明显获取这个提供者的包名,
default Map<String, ?> getJpaPropertyMap(PersistenceUnitInfo pui) {
return getJpaPropertyMap();
}
获得提供者的属性,那返回值是一个Map,那下边都是获取提供者的具体信息
/**
* Return a Map of vendor-specific JPA properties,
* typically based on settings in this JpaVendorAdapter instance.
* <p>Note that there might be further JPA properties defined on the
* EntityManagerFactory bean, which might potentially override individual
* JPA property values specified here.
* @return a Map of JPA properties, as accepted by the standard JPA bootstrap
* facilities, or an empty Map if there are no properties to expose
* @see javax.persistence.Persistence#createEntityManagerFactory(String, Map)
*/
default Map<String, ?> getJpaPropertyMap() {
return Collections.emptyMap();
}
/**
* Return the vendor-specific JpaDialect implementation for this
* provider, or {@code null} if there is none.
*/
@Nullable
default JpaDialect getJpaDialect() {
return null;
}
/**
* Return the vendor-specific EntityManagerFactory interface
* that the EntityManagerFactory proxy is supposed to implement.
* <p>If the provider does not offer any EntityManagerFactory extensions,
* the adapter should simply return the standard
* {@link javax.persistence.EntityManagerFactory} class here.
* @since 2.5.2
*/
default Class<? extends EntityManagerFactory> getEntityManagerFactoryInterface() {
return EntityManagerFactory.class;
}
/**
* Return the vendor-specific EntityManager interface
* that this provider's EntityManagers will implement.
* <p>If the provider does not offer any EntityManager extensions,
* the adapter should simply return the standard
* {@link javax.persistence.EntityManager} class here.
*/
default Class<? extends EntityManager> getEntityManagerInterface() {
return EntityManager.class;
}
/**
* Optional callback for post-processing the native EntityManagerFactory
* before active use.
* <p>This can be used for triggering vendor-specific initialization processes.
* While this is not expected to be used for most providers, it is included
* here as a general extension hook.
*/
default void postProcessEntityManagerFactory(EntityManagerFactory emf) {
}
例如getEntityManagerInterface这个是获取持久层的管理器,那下面我们找一个子类来看一下,他的实现类里面的逻辑,
我们就看一下AbstractJpaVendorAdapter,我们简单看一下,定义了一个数据库
public abstract class AbstractJpaVendorAdapter implements JpaVendorAdapter {
private Database database = Database.DEFAULT;
@Nullable
private String databasePlatform;
private boolean generateDdl = false;
private boolean showSql = false;
databasePlatform这个呢是一个数据库的平台,generateDdl是否生成Ddl,是否显示SQL,下面都是dataBase的get/set方法,
/**
* Specify the target database to operate on, as a value of the {@code Database} enum:
* DB2, DERBY, H2, HSQL, INFORMIX, MYSQL, ORACLE, POSTGRESQL, SQL_SERVER, SYBASE
* <p><b>NOTE:</b> This setting will override your JPA provider's default algorithm.
* Custom vendor properties may still fine-tune the database dialect. However,
* there may nevertheless be conflicts: For example, specify either this setting
* or Hibernate's "hibernate.dialect_resolvers" property, not both.
*/
public void setDatabase(Database database) {
this.database = database;
}
/**
* Return the target database to operate on.
*/
protected Database getDatabase() {
return this.database;
}
/**
* Specify the name of the target database to operate on.
* The supported values are vendor-dependent platform identifiers.
*/
public void setDatabasePlatform(@Nullable String databasePlatform) {
this.databasePlatform = databasePlatform;
}
/**
* Return the name of the target database to operate on.
*/
@Nullable
protected String getDatabasePlatform() {
return this.databasePlatform;
}
那在setDatabase的时候,我们可以看到DB2, DERBY, H2, HSQL, INFORMIX, MYSQL, ORACLE, POSTGRESQL, SQL_SERVER,
SYBASE支持的数据库类型,DB2, DERBY是一个微型的数据库,H2是一个内存数据库,下面的各种方法,你们有兴趣的自己
可以看一下,非常简单,那对于Eclipse和Hibernate这两个实现类呢,你们可以看一下,和我们现在讲的整个类异曲同工
现在我们再看一下在SpringMVC中,使用的适配器,这里使用的适配器还是非常关键的,
他的包是在package org.springframework.web.servlet;这个包下的,我们可以看到,HandlerAdapter有好几个实现,
包括SimpleControllerHandlerAdapter简单的Controller Handler适配器,还有servlet这个类型的,还有RequestMapping,
还有HttpRequest,还有一个抽象类便于扩展的Adapter,那SpringMVC中的适配器到底解决什么问题呢,我们一起来看看源码,
首先进入我们Spring的前端控制器,DispatcherServlet这个类可以说是SpringMVC的一个核心类,我们可以把这个类理解成
我们适配器中的client,也就是Test类,它是一个上帝视角,主要作用是在于通过处理映射器,也就是HandlerMapping,来找到
对应的Handler,对应的Handler呢就是Controller,我们可以理解成一个Controller,一个Servlet,或者是HttpServletHandler,
都是指Controller,同时执行Controller里面对应的方法,并且返回ModelAndView,那这个核心类里面重点的方法,就是doDispatcher,
/**
* Process the actual dispatching to the handler.
* <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
* to find the first that supports the handler class.
* <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
* themselves to decide which methods are acceptable.
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception in case of any kind of processing failure
*/
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = processedRequest != request;
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
try {
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
}
applyDefaultViewName(request, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
return;
}
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
我们看看下边,上边是一些声明,mappedHandler通过getHandler方法,入参放入processedRequest,通过这里来映射对应的Controller,
然后继续往下看,HandlerAdapter,通过getHandlerAdapter这个方法,来获取对应的适配器,下面对request里面进行了一些判断,例如GET
HEAD,等等,最下边mv,mv是什么类型呢,往上看一下,ModelAndView mv = null;mv是ModelAndView,继续,通过适配器ha的handle方法,
返回对应的ModelAndView对象,那这里面用适配器解决什么问题呢,对于Controller我们可以理解成它是一个被适配者,也就是我们讲的,
220V交流电,那么看一下Controller这个接口,mvc下的Controller接口,我们看一下他的具体实现类,这里面关于Controller还是有很多实现类的,
那因为Controller里面有这么多的实现类,所以调用方式就是确定的,那如果我们直接调用Controller里面的方法,那我们就的判断具体呢
是使用的哪个实现类呢,我们可以通过instanceof来判断,而这里面还会写一些if else这种,如果以后我们自己扩展一个自己类型的Controller,
比如我们实现了Controller这个接口,我们还要修改刚刚说的if else的判断逻辑,本身这样就违背了开闭原则,那在SpringMVC中呢,是如何使用
Adapter模式,解决这个问题呢,这就又回到HandlerAdapter这个对象,Spring本身提供了一个适配器接口,我们看一下他的实现,我们可以认为
这里的实现都是为了实现刚刚Controlle里面的实现类,通过这个适配器,使每一个Controller的实现呢,都能找到对应的适配器实现类,让适配器
执行相应的方法,这样的话我们在扩展Controller的时候呢,只需要增加一个适配器类,就可以完成SpringMVC的扩展了,另外再看一下support这个
方法,这里传入的是一个Object类型的Handler
/**
* Given a handler instance, return whether or not this {@code HandlerAdapter}
* can support it. Typical HandlerAdapters will base the decision on the handler
* type. HandlerAdapters will usually only support one handler type each.
* <p>A typical implementation:
* <p>{@code
* return (handler instanceof MyHandler);
* }
* @param handler handler object to check
* @return whether or not this object can use the given handler
*/
boolean supports(Object handler);
刚刚我们也看了,他具体的实现也是用instanceof判断一下,它是具体的哪一种的Handler,也就是说这个Controller,对于我的Adapter,
如果不支持的话,那他就会返回一个false,很必然的,我们看一下Simple的,这里面就会返回false
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return ((Controller) handler).handleRequest(request, response);
}
@Override
public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
}
}
告诉它不支持,我们再回到DispatcherServlet核心方法中
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
这里面通过getHandlerAdapter这个方法传入对应的Handler,来获取对应的Adapter,从而使每一个Handler呢,
都会有对应的Adapter,那我们看一下这个方法的实现,这个方法的实现还是比较简单的,
/**
* Return the HandlerAdapter for this handler object.
* @param handler the handler object to find an adapter for
* @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.
*/
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
你们可以来看一下,一个循环,进行一个判断的支持,然后把ha他进行返回,刚刚我们说的SimpleControllerHandlerAdapter就是我们
常常说的,最简单的Controller类,一个适配器,SimpleControllerHandlerAdapter,那讲到这里呢,相信你们通过学习适配器模式,
对适配器肯定是加深理解的,另外通过我们对JDK以及呢,Spring开源框架的讲解,相信大家对SpringMVC,处理Controller,
一些逻辑以及为什么使用适配器模式,也会有所提高的,那希望您们通过这个能够对适配器模式理解透,加深了解,应用自如