首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

spring的AOP调用(5)RegexpMethodPointcutAdvisor完整实现代码

2012-11-05 
spring的AOP调用(五)RegexpMethodPointcutAdvisor完整实现代码spring的AOP调用(五)RegexpMethodPointcutAd

spring的AOP调用(五)RegexpMethodPointcutAdvisor完整实现代码
spring的AOP调用(五)RegexpMethodPointcutAdvisor完整实现代码

由于采用<aop:config>配置的方式在自己的demo中没有任何问题,在公司的工程项目中却出现了调用三次的现象,无法解决。所以在此尝试用RegexpMethodPointcutAdvisor来实现AOP处理。

主要配置文件如下,applicationContext.xml:
拦截保存操作的方法
<bean id="saveMethodAOPAdvice"
ref="saveMethodAOP" />
<property name="patterns">
   <list>
    <value>.*DAOImpl\.save.*</value>
   </list>
</property>
</bean>
<bean id="deleteMethodAOPAdvice"
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项目中和公司的项目中都只调用一次,没有出现重复调用三次的问题。

热点排行