Spring基础:AOP编程(3)

[size=x-large][b]基于切面的AOP编程[/b][/size]

通过Advice,可以创建方法前,后,环绕之类的增强,但是这是类级别的增强,如果想要深入到方法级别,就需要配合使用切点Pointcut。Advice和Pointcut组合就形成了一个切面。切面增强就是基于方法层面的。

1.切点(Pointcut)
用于过滤类,getClassFilter()返回ClassFilter类,在这个类里面有一个方法用于判断该对象是否满足匹配条件,boolean matches(Class<?> clazz)。
用于过滤方法,getMethodMatcher()返回MethodMatcher,在该类里面有boolean matches(Method method, Class<?> targetClass)用于静态匹配方法,boolean matches(Method method, Class<?> targetClass, Object[] args)用于动态匹配。

2 切点的分类
[list]
[*]StaticMethodMatcherPointcut 静态方法切点
[*]DynamicMethodMatcherPointcut 动态方法切点
[*]AnnotationMatchingPointcut 注解切点
[*]AspectJExpressionPointcut 支持AspectJ语法的表达式切点
[*]ControlFlowPointcut 流程切点
[*]ComposablePointcut 复合切点
[/list]

静态方法切点又分两种
[list]
[*]NameMatchMethodPointcut 用于方法名匹配
[*]JdkRegexpMethodPointcut 用于正则匹配
[/list]

3 切面
切面分三种
[list]
[*]Advisor 一般切面,仅包含一个增强方法,不包含切点信息
[*]PointcutAdvisor 包含切点的切面,用起来比较灵活
[*]IntroductionAdvisor 引介切面
[/list]

而PointcutAdvisor又分为以下6种
[list]
[*]DefaultPointcutAdvisor 最常用的切面,可以通过任意组合切点和增强构建切面
[*]NameMatchMethodPointcutAdvisor 通过方法名来定义切面
[*]RegexpMethodPointcutAdvisor 通过正则表达式匹配方法名来定义切面
[*]StaticMethodMatcherPointcutAdvisor 默认情况下,匹配所有目标类
[*]AspectJExpressionPointcutAdvisor 用AspectJ切点表达式来匹配
[*]AspectJPointcutAdvisor 用AspectJ语法来匹配
[/list]

4 例子
准备基础类和一个增强类

public class Waiter {
public void greetTo(String name) {
System.out.println("waiter greet to " + name + "...");
}

public void serveTo(String name) {
System.out.println("waier serving to " + name + "...");
}
}
public class Seller {
public void greetTo(String name) {
System.out.println("seller greet to " + name + "...");
}
}个
// 前置增强
public class GreetingBeforeAdvice implements MethodBeforeAdvice {

public void before(Method method, Object[] args, Object obj)
throws Throwable {
System.out.println(obj.getClass().getName() + "." + method.getName());
String clientName = (String) args[0];
System.out.println("How are you! Mr." + clientName);
}
}

4.1 静态方法匹配:

public class GreetingAdvisor extends StaticMethodMatcherPointcutAdvisor {
public boolean matches(Method method, Class<?> targetClass) {
return "greetTo".equals(method.getName());
}
public ClassFilter getClassFilter() {
return new ClassFilter() {
public boolean matches(Class<?> clazz) {
return Waiter.class.isAssignableFrom(clazz);
}
};
}
}

因为GreetingAdvisor类中已经包含切点信息,所以只要配置增强类即可。

<bean id="waiterTarget" class="com.firethewhole.maventest07.advisor.Waiter"/>
<bean id="sellerTarget" class="com.firethewhole.maventest07.advisor.Seller"/>
<bean id="greetingAdvice" class="com.firethewhole.maventest07.advisor.GreetingBeforeAdvice"/>
<bean id="greetingAdvisor" class="com.firethewhole.maventest07.advisor.GreetingAdvisor"
p:advice-ref="greetingAdvice"/>
<bean id="parent" abstract="true" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="greetingAdvisor"
p:proxyTargetClass="true"/>
<bean id="waiter" parent="parent" p:target-ref="waiterTarget"/>
<bean id="seller" parent="parent" p:target-ref="sellerTarget"/>


测试:

String configPath = "com/firethewhole/maventest07/advisor/beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
Waiter waiter = (Waiter) ctx.getBean("waiter");
Seller seller = (Seller) ctx.getBean("seller");
waiter.greetTo("John");
waiter.serveTo("John");
seller.greetTo("John");


输出:
只有Waiter类的greetTo方法被织入增强
[color=blue]
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.John
waiter greet to John...
waier serving to John...
seller greet to John...
[/color]

4.2 正则匹配方法名增强

<bean id="regexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
p:advice-ref="greetingAdvice">
<property name="patterns">
<list><value>.*greet.*</value></list>
</property>
</bean>
<bean id="waiter1" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="regexpAdvisor"
p:target-ref="waiterTarget"
p:proxyTargetClass="true"/>


Waiter waiter1 = (Waiter) ctx.getBean("waiter1");
waiter1.greetTo("John");
waiter1.serveTo("John");


输出:
只有greetTo方法被织入增强
[color=blue]
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.John
waiter greet to John...
waier serving to John...
[/color]

4.3 动态方法匹配
动态方法匹配之前都会先进性静态方法匹配,如果失败才会进行

public class GreetingDynamicPointcut extends DynamicMethodMatcherPointcut {
private static List<String> specialClientList = new ArrayList<String>();
static {
specialClientList.add("John");
specialClientList.add("Tom");
}
public ClassFilter getClassFilter() {
return new ClassFilter() {
public boolean matches(Class<?> clazz) {
System.out.println("调用getClassFilter()对" + clazz.getName() + "做静态检查。");
return Waiter.class.isAssignableFrom(clazz);
}
};
}
public boolean matches(Method method, Class<?> clazz) {
System.out.println("调用matches(method,clazz)对" + clazz.getName() + "." + method.getName() + "做静态检查。");
return "greetTo".equals(method.getName());
}
public boolean matches(Method method, Class<?> clazz, Object[] args) {
System.out.println("调用matches(method,clazz)对" + clazz.getName() + "." + method.getName() + "做动态检查。");
String clientName = (String) args[0];
return specialClientList.contains(clientName);
}
}


<bean id="greetingDynamicPointcut" class="com.firethewhole.maventest07.advisor.GreetingDynamicPointcut"/>
<bean id="dynamicAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"
p:pointcut-ref="greetingDynamicPointcut"
p:advice-ref="greetingAdvice"/>
<bean id="waiter2" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="dynamicAdvisor"
p:target-ref="waiterTarget"
p:proxyTargetClass="true"/>


Waiter waiter2 = (Waiter) ctx.getBean("waiter2");
waiter2.greetTo("Peter");
waiter2.serveTo("Peter");
waiter2.greetTo("John");
waiter2.serveTo("John");

输出:
[color=blue]
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.serveTo做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.toString做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.clone做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做动态检查。
waiter greet to Peter...
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.serveTo做静态检查。
waier serving to Peter...
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做动态检查。
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.John
waiter greet to John...
waier serving to John...
[/color]

4.4 流程切面
对配置在某一个类中的某一个方法中直接或间接使用的类进行增强

public class WaiterDelegate {
private Waiter waiter;
public void setWaiter(Waiter waiter) {
this.waiter = waiter;
}
public void service(String name) {
waiter.greetTo(name);
waiter.serveTo(name);
}
}


<bean id="controlFlowPointcut" class="org.springframework.aop.support.ControlFlowPointcut">
<constructor-arg type="java.lang.Class" value="com.firethewhole.maventest07.advisor.WaiterDelegate"/>
<constructor-arg type="java.lang.String" value="service"/>
</bean>
<bean id="controlFlowAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"
p:pointcut-ref="controlFlowPointcut"
p:advice-ref="greetingAdvice"/>
<bean id="waiter3" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="controlFlowAdvisor"
p:target-ref="waiterTarget"
p:proxyTargetClass="true"/>


Waiter waiter3 = (Waiter) ctx.getBean("waiter3");
WaiterDelegate wd = new WaiterDelegate();
wd.setWaiter(waiter3);
waiter3.serveTo("Peter");
waiter3.greetTo("Peter");
wd.service("Peter");


输出:
只有流程切点中的才会被织入增强
[color=blue]
waier serving to Peter...
waiter greet to Peter...
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.Peter
waiter greet to Peter...
com.firethewhole.maventest07.advisor.Waiter.serveTo
How are you! Mr.Peter
waier serving to Peter...
[/color]

4.5 复合增强

public class GreetingComposablePointcut {
public Pointcut getIntersectionPointcut() {
ComposablePointcut cp = new ComposablePointcut();
Pointcut pt1 = new ControlFlowPointcut(WaiterDelegate.class, "service");
Pointcut pt2 = new NameMatchMethodPointcut();
((NameMatchMethodPointcut)pt2).addMethodName("greetTo");
return cp.intersection(pt1).intersection(pt2);
}
}


<bean id="gcp" class="com.firethewhole.maventest07.advisor.GreetingComposablePointcut"/>
<bean id="compsableAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"
p:pointcut="#{gcp.getIntersectionPointcut()}"
p:advice-ref="greetingAdvice"/>
<bean id="waiter4" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="compsableAdvisor"
p:target-ref="waiterTarget"
p:proxyTargetClass="true"/>


Waiter waiter4 = (Waiter) ctx.getBean("waiter4");
WaiterDelegate wd2 = new WaiterDelegate();
wd2.setWaiter(waiter4);
waiter4.serveTo("Peter");
waiter4.greetTo("Peter");
wd2.service("Peter");


输出:
只有流程切点中的方法名为greetTo才会被织入增强
[color=blue]
waier serving to Peter...
waiter greet to Peter...
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.Peter
waiter greet to Peter...
waier serving to Peter...
[/color]

4.6 引介增强
引介增强是类级别的织入,主要的类有DefaultIntroductionAdvisor,配置方法如下:

<bean id="introduceAdvisor" class="org.springframework.aop.support.DefaultIntroductionAdvisor">
<constructor-arg>
<bean class="com.firethewhole.maventest07.introduce.ControllablePerformanceMonitor/>
</constructor-arg>
</bean>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值