Spring之AOP适配器模式

简介: Spring架构中涉及了很多设计模式,本文来介绍下Spring中在AOP实现时Adapter模式的使用。AOP本质上是Java动态代理模式的实现和适配器模式的使用,关于这两种设计模式的具体介绍烦请参考我之前的文章


 Spring架构中涉及了很多设计模式,本文来介绍下Spring中在AOP实现时Adapter模式的使用。AOP本质上是Java动态代理模式的实现和适配器模式的使用,关于这两种设计模式的具体介绍烦请参考我之前的文章

Java代理模式

Java适配器模式(adapter)

文章目录

   Spring中适配器模式

       一、AOP案例

           1.相关依赖

           2.创建目标对象

           3.创建通知

           4.配置文件

           5.测试

       二、适配器应用解析

           1.Advice体系结构

           2.适配器的实现

               2.1Adaptee

               2.2target

               2.3Adapter

               2.4Client

Spring中适配器模式

一、AOP案例

 Spring中的AOP的实现方式有多种,而且每种实现方式中的通知类型也比较多,本文以Spring自带的Schema-base方式中的前置通知来说明。详细介绍移步 Spring之AOP详解

1.相关依赖

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>4.3.21.RELEASE</version>
</dependency>
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
</dependency>
<dependency>
  <groupId>aopalliance</groupId>
  <artifactId>aopalliance</artifactId>
  <version>1.0</version>
</dependency>

2.创建目标对象

/**
 * 目标对象 接口
 * @author 波波烤鸭
 * @email dengpbs@163.com
 *
 */
public interface SomeService {
  public void doSome();
}
/**
 * 目标对象
 * @author 波波烤鸭
 * @email dengpbs@163.com
 *
 */
public class SomeServiceImpl implements SomeService {
  @Override
  public void doSome() {
    System.out.println("目标对象....方法执行了");
  }
}

3.创建通知

/**
 * 前置通知
 *    需要实现MethodBeforeAdvice接口
 * @author 波波烤鸭
 * @email dengpbs@163.com
 *
 */
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
  /**
   * method 目标方法
   * args 目标方法参数列表
   * target 目标对象
   */
  @Override
  public void before(Method method, Object[] args, Object target) throws Throwable {
    System.out.println("前置通知执行了....");
  }
}

4.配置文件

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
  <!-- 注册目标类 -->
  <bean id="someServiceImpl" class="com.dpb.service.SomeServiceImpl" ></bean>
  <!-- 注册前置通知 -->
  <bean class="com.dpb.schema.MyMethodBeforeAdvice" id="myMethodBeforeAdvice"></bean>
  <!-- 注册代理类 -->
  <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
    <!-- 指定目标对象 -->
    <property name="target" ref="someServiceImpl"/>
    <!-- 指定目标类实现的所有接口 -->
    <property name="interfaces" value="com.dpb.service.SomeService"/>
    <!-- 指定切面 -->
    <property name="interceptorNames" >
      <list>
        <value>myMethodBeforeAdvice</value>
      </list>
    </property>
  </bean>
</beans>

5.测试

@Test
public void test1() {
  ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
  // 注意通过getBean获取增强的代理类!!!
  SomeService some = ac.getBean("proxyFactoryBean",SomeService.class);
  some.doSome();
}

输出:

image.png

说明我们配置的前置通知生效了,在目标方法执行之前执行了。

二、适配器应用解析

1.Advice体系结构

image.png

说明:

   advice的类型有:BeforeAdvice,AfterReturningAdvice,ThrowsAdvice等

   每个类型的通知都有对应的拦截器

advice 拦截器

BeforeAdvice MethodBeforeAdviceInterceptor

AfterAdvice AfterReturningAdviceInterceptor

AfterAdvice ThrowsAdviceInterceptor

   Spring容器需要将每个具体的advice封装成对应的拦截器,返回给容器,这里对advice转换就需要用到适配器模式。

2.适配器的实现

 以前置通知为例

2.1Adaptee

public interface MethodBeforeAdvice extends BeforeAdvice {
  void before(Method method, Object[] args, Object target) throws Throwable;
}

2.2target

 Adapter的接口 AdvisorAdapter

public interface AdvisorAdapter {
  // 判断通知类型是否匹配
  boolean supportsAdvice(Advice advice);
  // 获取对应的拦截器
  MethodInterceptor getInterceptor(Advisor advisor);
}

2.3Adapter

 MethodBeforeAdviceAdapter

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
  @Override
  public boolean supportsAdvice(Advice advice) {
    return (advice instanceof MethodBeforeAdvice);
  }
  @Override
  public MethodInterceptor getInterceptor(Advisor advisor) {
    MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
    // 通知类型匹配对应的拦截器
    return new MethodBeforeAdviceInterceptor(advice);
  }
}

2.4Client

 代理类通过DefaultAdvisorAdapterRegistry类来注册相应的适配器。

image.pngimage.png


public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
  private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);
  /**
   * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
   */
  public DefaultAdvisorAdapterRegistry() {
    // 注册相应的适配器
    registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
    registerAdvisorAdapter(new AfterReturningAdviceAdapter());
    registerAdvisorAdapter(new ThrowsAdviceAdapter());
  }
  // 包装类  将通知转换为了 对应的适配器
  // 本案例中将 MyMethodBeforeAdvice转换为了MethodBeforeAdviceAdapter
  @Override
  public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
    if (adviceObject instanceof Advisor) {
      return (Advisor) adviceObject;
    }
    if (!(adviceObject instanceof Advice)) {
      throw new UnknownAdviceTypeException(adviceObject);
    }
    Advice advice = (Advice) adviceObject;
    if (advice instanceof MethodInterceptor) {
      // So well-known it doesn't even need an adapter.
      return new DefaultPointcutAdvisor(advice);
    }
    for (AdvisorAdapter adapter : this.adapters) {
      // Check that it is supported.
      if (adapter.supportsAdvice(advice)) {
        return new DefaultPointcutAdvisor(advice);
      }
    }
    throw new UnknownAdviceTypeException(advice);
  }
  // 获取适配器对应的所有的拦截器
  @Override
  public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
    List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
    Advice advice = advisor.getAdvice();
    if (advice instanceof MethodInterceptor) {
      interceptors.add((MethodInterceptor) advice);
    }
    for (AdvisorAdapter adapter : this.adapters) {
      if (adapter.supportsAdvice(advice)) {
                // 调用了适配器的方法
        interceptors.add(adapter.getInterceptor(advisor));
      }
    }
    if (interceptors.isEmpty()) {
      throw new UnknownAdviceTypeException(advisor.getAdvice());
    }
    return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
  }
  @Override
  public void registerAdvisorAdapter(AdvisorAdapter adapter) {
    this.adapters.add(adapter);
  }
}

本案例中的适配器中的方法是

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
  // 前置通知方法
  this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
  // 目标对象的方法
  return mi.proceed();
}

~ 好了 AOP中的适配器的分析就到此了。关于AOP中的代理的实现抽空再来分析


相关文章
|
1月前
|
监控 Java 开发者
Spring AOP动态代理
Spring AOP动态代理
43 1
|
1月前
|
Java Spring 容器
Spring的AOP失效场景详解
Spring的AOP失效场景详解
111 0
|
2月前
|
XML Java 编译器
Spring AOP初步理解及使用
Spring AOP初步理解及使用
49 0
|
2月前
|
Java Spring
[Spring]aop的配置与使用
[Spring]aop的配置与使用
40 0
[Spring]aop的配置与使用
|
29天前
|
设计模式 Java Maven
Spring Aop 底层责任链思路实现-springaopdi-ceng-ze-ren-lian-si-lu-shi-xian
Spring Aop 底层责任链思路实现-springaopdi-ceng-ze-ren-lian-si-lu-shi-xian
35 1
|
2月前
|
XML Java 数据格式
5个点轻松搞定Spring AOP底层实现原理
AOP 也是 Spring 中一个较为重要的内容,相对于传统的 OOP 模式,AOP 有很多让人难以理解的地方,本篇文章将向大家介绍 AOP 的实现方法及其底层实现,内容包括:
46 1
|
22天前
|
XML Java Maven
Spring之Aop的注解使用
Spring之Aop的注解使用
|
28天前
|
Java Spring
Spring 如何实现 AOP
Spring 如何实现 AOP
17 0
|
1月前
|
Java 编译器 程序员
Spring AOP 和 AspectJ 的比较
Spring AOP 和 AspectJ 的比较
37 0
|
1月前
|
Java Spring
【spring(三)】AOP总结
【spring(三)】AOP总结