Spring-AOP 静态普通方法名匹配切面操作

2022-07-22,,,,

概述

staticmethodmatcherpointcutadvisor代表一个静态方法匹配切面,它通过staticmethodmatcherpointcut来定义切点,并通过类过滤和方法名来匹配所定义的切点.

实例

代码已托管到github—> https://github.com/yangshangwei/springmaster

我们假设我们业务类中 waiter和 seller中都有同名的greetto()方法.

业务类waiter

package com.xgj.aop.spring.advisor.staticmethodmatcherpointcutadvisor;
public class waiter {
	/**
	 * 
	 * 
	 * @title: greetto
	 * 
	 * @description:
	 * 
	 * @param name
	 * 
	 * @return: void
	 */
	public void greetto(string name) {
		system.out.println("waiter greet to " + name);
	}
	/**
	 * 
	 * 
	 * @title: serverto
	 * 
	 * @description:
	 * 
	 * @param name
	 * 
	 * @return: void
	 */
	public void serverto(string name) {
		system.out.println("waiter server to " + name);
	}
}

业务类seller

package com.xgj.aop.spring.advisor.staticmethodmatcherpointcutadvisor;
public class seller {
 /**
  * 
  * 
  * @title: greetto
  * 
  * @description: 和waiter类中的同名的方法,目的是为了验证仅仅织入了waiter类中的greetto方法
  * 
  * @param name
  * 
  * @return: void
  */
 public void greetto(string name) {
  system.out.println("seller greet to " + name);
 }
}

现在我们希望通过staticmethodmatcherpointcutadvisor定义一个切面,在waiter#greetto()方法调用前织入一个增强,即连接点为waiter#greetto()方法调用前的位置。

切面代码

package com.xgj.aop.spring.advisor.staticmethodmatcherpointcutadvisor;
import java.lang.reflect.method;
import org.springframework.aop.classfilter;
import org.springframework.aop.support.staticmethodmatcherpointcutadvisor;
/**
 * 
 * 
 * @classname: greetingadvisor
 * 
 * @description: 切面类
 * 
 * @author: mr.yang
 * 
 * @date: 2017年8月18日 下午8:27:52
 */
public class greetingadvisor extends staticmethodmatcherpointcutadvisor {
	private static final long serialversionuid = 1l;
	/**
	 * 重写matches方法,切点方法匹配规则:方法名为greetto
	 */
	@override
	public boolean matches(method method, class<?> targetclass) {
		return "greetto".equals(method.getname());
	}
	/**
	 * 默认情况下,匹配所有的类,重写getclassfilter,定义匹配规则 切点类型匹配规则,为waiter的类或者之类
	 */
	public classfilter getclassfilter() {
		return new classfilter() {
			@override
			public boolean matches(class<?> clazz) {
				return waiter.class.isassignablefrom(clazz);
			}
		};
	}
}

staticmethodmatcherpointcutadvisor 抽象类唯一需要定义的是matches()方法,在默认情况下,该切面匹配所有的类,这里通过覆盖getclassfilter()方法,让它仅匹配waiter类及其子类。

当然,advisor还需要一个增强类的配合 .

我们来定义一个前置增强

package com.xgj.aop.spring.advisor.staticmethodmatcherpointcutadvisor;
import java.lang.reflect.method;
import org.springframework.aop.methodbeforeadvice;
/**
 * 
 * 
 * @classname: greetbeforeadivce
 * 
 * @description: 前置增强
 * 
 * @author: mr.yang
 * 
 * @date: 2017年8月18日 下午8:27:40
 */
public class greetbeforeadivce implements methodbeforeadvice {
	@override
	public void before(method method, object[] args, object target)
			throws throwable {
		// 输出切点
		system.out.println("pointcut:" + target.getclass().getname() + "."
				+ method.getname());
		string clientname = (string) args[0];
		system.out.println("how are you " + clientname + " ?");
	}
}

我们使用spring配置来定义切面等信息

<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
	xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!-- 配置切面:静态方法匹配切面 -->
	
	<!-- waiter目标类 -->
	<bean id="waitertarget" class="com.xgj.aop.spring.advisor.staticmethodmatcherpointcutadvisor.waiter"/>
	<!-- seller目标类 -->
	<bean id="sellertarget" class="com.xgj.aop.spring.advisor.staticmethodmatcherpointcutadvisor.seller"/>
	
	<!-- 前置增强 -->
	<bean id="greetbeforeadvice" class="com.xgj.aop.spring.advisor.staticmethodmatcherpointcutadvisor.greetbeforeadivce"/>
	
	<!-- 切面 -->
	<bean id="greetadvicesor" class="com.xgj.aop.spring.advisor.staticmethodmatcherpointcutadvisor.greetingadvisor"
		p:advice-ref="greetbeforeadvice"/> <!-- 向切面注入一个前置增强 -->
		
	<!-- 通过父bean,配置公共的信息 -->
	<bean id="parent" abstract="true"  
		class="org.springframework.aop.framework.proxyfactorybean"
		p:interceptornames="greetadvicesor"
		p:proxytargetclass="true"/>
	<!-- waiter代理 -->
	<bean id="waiter" parent="parent" p:target-ref="waitertarget"/>
	<!-- seller代理 -->
	<bean id="seller" parent="parent" p:target-ref="sellertarget"/>
	
</beans>

单元测试类

package com.xgj.aop.spring.advisor.staticmethodmatcherpointcutadvisor;
import org.junit.test;
import org.springframework.context.applicationcontext;
import org.springframework.context.support.classpathxmlapplicationcontext;
/**
 * 
 * 
 * @classname: staticmethodmatcherpointcutadvisortest
 * 
 * @description: 测试类
 * 
 * @author: mr.yang
 * 
 * @date: 2017年8月18日 下午8:29:28
 */
public class staticmethodmatcherpointcutadvisortest {
	@test
	public void test() {
		// 加载配置文件,启动容器
		applicationcontext ctx = new classpathxmlapplicationcontext(
				"classpath:com/xgj/aop/spring/advisor/staticmethodmatcherpointcutadvisor/conf-advisor.xml");
		// 从容器中获取bean
		waiter waiter = ctx.getbean("waiter", waiter.class);
		seller seller = ctx.getbean("seller", seller.class);
		// 调用业务方法
		waiter.greetto("xiaogongjiang");
		waiter.serverto("xiaogongjiang");
		seller.greetto("xiaogongjiang");
	}
}

运行结果:

我们可以看到切面仅仅织入了wwaiter.greetto()方法调用前的连接点上, waiter.serverto()和seller.greetto()方法并没有织入切面。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

《Spring-AOP 静态普通方法名匹配切面操作.doc》

下载本文的Word格式文档,以方便收藏与打印。