spring的AOP调用(五)RegexpMethodPointcutAdvisor完整实现代码
由于采用<aop:config>配置的方式在自己的demo中没有任何问题,在公司的工程项目中却出现了调用三次的现象,无法解决。所以在此尝试用RegexpMethodPointcutAdvisor来实现AOP处理。
主要配置文件如下,applicationContext.xml:
拦截保存操作的方法
<bean id="saveMethodAOPAdvice"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
lazy-init="true">
<property name="advice" ref="saveMethodAOP" />
<property name="patterns">
<list>
<value>.*DAOImpl\.save.*</value>
</list>
</property>
</bean>
<bean id="deleteMethodAOPAdvice"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
lazy-init="true">
<property name="advice" ref="deleteMethodAOP" />
<property name="patterns">
<list>
<value>.*DAOImpl\.delete.*</value>
</list>
</property>
</bean>
其中的正则表达式表示所有的呃DAOImpl结尾的save和deletee方法,在这里处理正则的是
JdkRegexpMethodPointcut类,如果需要写其他正则表达式,可以调用这个方法来单元测试:
package com.sillycat.easyaop;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TestMain {
public static void main(String[] args) {
String str1 = "com.sillycat.easyaop.dao.impl.RoleDAOImpl.save";
String str2 = "com.sillycat.easyaop.dao.impl.UserDAOImpl.save";
String str3 = "com.sillycat.easyaop.dao.impl.BaseDAOImpl.save";
Pattern pattern = Pattern.compile(
".*[^(Role)]DAOImpl[.]save.*");
Matcher matcher1 = pattern.matcher(str1);
Matcher matcher2 = pattern.matcher(str2);
Matcher matcher3 = pattern.matcher(str3);
System.out.println(matcher1.matches());
System.out.println(matcher2.matches());
System.out.println(matcher3.matches());
}
}
我们的实现类SaveMethodAOPImpl.java如下:
package com.sillycat.easyaop.service.aop;
import javax.annotation.Resource;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.ReflectiveMethodInvocation;
import org.springframework.stereotype.Service;
import com.sillycat.easyaop.commons.utils.StringUtil;
import com.sillycat.easyaop.dao.RoleDao;
import com.sillycat.easyaop.model.Role;
@Service("saveMethodAOP")
public class SaveMethodAOPImpl implements MethodInterceptor {
private static Log log = LogFactory.getLog(SaveMethodAOPImpl.class);
private static final String BASE_MANAGER_SAVE = "com.sillycat.easyaop.dao.impl.RoleDAOImpl";
private RoleDao roleDao;
@Resource(name = "roleDao")
public void setRoleDao(RoleDao roleDao) {
this.roleDao = roleDao;
}
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
log.debug("target name is : " + getTargetName(methodInvocation));
log.debug("args is : " + methodInvocation.getArguments()[0]);
if (checkIfNeedProccess(methodInvocation, methodInvocation
.getArguments()[0])) {
log.debug("object is extends Role,begin to ivoke roleDAO!");
roleDao.save((Role) methodInvocation.getArguments()[0]);
}
// 执行原始方法
methodInvocation.proceed();
return null;
}
private String getTargetName(MethodInvocation methodInvocation) {
String action = methodInvocation.getMethod().getDeclaringClass()
.getName();
/**
* 由于Spring使用了Cglib代理,导致不能直接取得目标类名,需作此转换
*/
if (methodInvocation instanceof ReflectiveMethodInvocation) {
Object proxy = ((ReflectiveMethodInvocation) methodInvocation)
.getProxy();
action = getCompleteTargetName(proxy.toString());
}
return action;
}
private boolean checkIfNeedProccess(MethodInvocation methodInvocation,
Object obj) {
boolean flag = false;
if (!BASE_MANAGER_SAVE
.equalsIgnoreCase(getTargetName(methodInvocation))
&& (obj instanceof Role)) {
flag = true;
}
return flag;
}
private String getCompleteTargetName(String target) {
String className = "";
if (StringUtil.isNotBlank(target)) {
className = target;
int loc = className.indexOf("@");
if (loc >= 0) {
className = className.substring(0, loc);
}
}
return className;
}
}
本来费尽周折想在方法里面取得调用的类名是要用来过滤基类DAO方法RoleDAOImpl的,结果发现不行,在启动的时候,spring就会报SaveMethodAOPImpl和RoleDAOImpl有循环依赖,所以就只能将RoleDAOImpl改名为RoleDaoImpl。BaseDAOImpl同理也改名为BaseDaoImpl了。不过取类名的方法还是留下,万一以后要用呢。
另外delete的方法和以上很类似,这里就不重复贴出了。
另外,这种调用方式在DEMO项目中和公司的项目中都只调用一次,没有出现重复调用三次的问题。
由于采用<aop:config>配置的方式在自己的demo中没有任何问题,在公司的工程项目中却出现了调用三次的现象,无法解决。所以在此尝试用RegexpMethodPointcutAdvisor来实现AOP处理。
主要配置文件如下,applicationContext.xml:
拦截保存操作的方法
<bean id="saveMethodAOPAdvice"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
lazy-init="true">
<property name="advice" ref="saveMethodAOP" />
<property name="patterns">
<list>
<value>.*DAOImpl\.save.*</value>
</list>
</property>
</bean>
<bean id="deleteMethodAOPAdvice"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
lazy-init="true">
<property name="advice" ref="deleteMethodAOP" />
<property name="patterns">
<list>
<value>.*DAOImpl\.delete.*</value>
</list>
</property>
</bean>
其中的正则表达式表示所有的呃DAOImpl结尾的save和deletee方法,在这里处理正则的是
JdkRegexpMethodPointcut类,如果需要写其他正则表达式,可以调用这个方法来单元测试:
package com.sillycat.easyaop;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TestMain {
public static void main(String[] args) {
String str1 = "com.sillycat.easyaop.dao.impl.RoleDAOImpl.save";
String str2 = "com.sillycat.easyaop.dao.impl.UserDAOImpl.save";
String str3 = "com.sillycat.easyaop.dao.impl.BaseDAOImpl.save";
Pattern pattern = Pattern.compile(
".*[^(Role)]DAOImpl[.]save.*");
Matcher matcher1 = pattern.matcher(str1);
Matcher matcher2 = pattern.matcher(str2);
Matcher matcher3 = pattern.matcher(str3);
System.out.println(matcher1.matches());
System.out.println(matcher2.matches());
System.out.println(matcher3.matches());
}
}
我们的实现类SaveMethodAOPImpl.java如下:
package com.sillycat.easyaop.service.aop;
import javax.annotation.Resource;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.ReflectiveMethodInvocation;
import org.springframework.stereotype.Service;
import com.sillycat.easyaop.commons.utils.StringUtil;
import com.sillycat.easyaop.dao.RoleDao;
import com.sillycat.easyaop.model.Role;
@Service("saveMethodAOP")
public class SaveMethodAOPImpl implements MethodInterceptor {
private static Log log = LogFactory.getLog(SaveMethodAOPImpl.class);
private static final String BASE_MANAGER_SAVE = "com.sillycat.easyaop.dao.impl.RoleDAOImpl";
private RoleDao roleDao;
@Resource(name = "roleDao")
public void setRoleDao(RoleDao roleDao) {
this.roleDao = roleDao;
}
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
log.debug("target name is : " + getTargetName(methodInvocation));
log.debug("args is : " + methodInvocation.getArguments()[0]);
if (checkIfNeedProccess(methodInvocation, methodInvocation
.getArguments()[0])) {
log.debug("object is extends Role,begin to ivoke roleDAO!");
roleDao.save((Role) methodInvocation.getArguments()[0]);
}
// 执行原始方法
methodInvocation.proceed();
return null;
}
private String getTargetName(MethodInvocation methodInvocation) {
String action = methodInvocation.getMethod().getDeclaringClass()
.getName();
/**
* 由于Spring使用了Cglib代理,导致不能直接取得目标类名,需作此转换
*/
if (methodInvocation instanceof ReflectiveMethodInvocation) {
Object proxy = ((ReflectiveMethodInvocation) methodInvocation)
.getProxy();
action = getCompleteTargetName(proxy.toString());
}
return action;
}
private boolean checkIfNeedProccess(MethodInvocation methodInvocation,
Object obj) {
boolean flag = false;
if (!BASE_MANAGER_SAVE
.equalsIgnoreCase(getTargetName(methodInvocation))
&& (obj instanceof Role)) {
flag = true;
}
return flag;
}
private String getCompleteTargetName(String target) {
String className = "";
if (StringUtil.isNotBlank(target)) {
className = target;
int loc = className.indexOf("@");
if (loc >= 0) {
className = className.substring(0, loc);
}
}
return className;
}
}
本来费尽周折想在方法里面取得调用的类名是要用来过滤基类DAO方法RoleDAOImpl的,结果发现不行,在启动的时候,spring就会报SaveMethodAOPImpl和RoleDAOImpl有循环依赖,所以就只能将RoleDAOImpl改名为RoleDaoImpl。BaseDAOImpl同理也改名为BaseDaoImpl了。不过取类名的方法还是留下,万一以后要用呢。
另外delete的方法和以上很类似,这里就不重复贴出了。
另外,这种调用方式在DEMO项目中和公司的项目中都只调用一次,没有出现重复调用三次的问题。