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.创建通知
/**
前置通知
@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();
}
输出:
说明我们配置的前置通知生效了,在目标方法执行之前执行了。
1.Advice 体系结构
说明:
advice 的类型有:BeforeAdvice,AfterReturningAdvice,ThrowsAdvice 等
每个类型的通知都有对应的拦截器
| advice | 拦截器 |
| --- | :-- |
| BeforeAdvice | MethodBeforeAdviceInterceptor |
| AfterAdvice | AfterReturningAdviceInterceptor |
| AfterAdvice | ThrowsAdviceInterceptor |
Spring 容器需要将每个具体的 advice 封装成对应的拦截器,返回给容器,这里对 advice 转换就需要用到适配器模式。
2.适配器的实现
以前置通知为例
2.1Adaptee
MethodBeforeAdvice
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 类来注册相应的适配器。
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
评论