AOP使用结总结
最近需要在原来的系统上添加业务日志,原有系统使用了spring2.0框架,立马想到用spring的AOP,由于考虑到系统运行环境在JDK1.4上,直接使用spring的AOP,不采用aspectj。
1、实现自己的日志业务类class LogMethodBeforeAdvice implements MethodBeforeAdvice
2、由于要记录方法指定参数和request中指定的对象,所以实现了自己的切入点,没有采用配置文件的方式
Class CustomPointcut implements Pointcut
public class CustomPointcut implements Pointcut{
private ClassFilter classFilter;
private MethodMatcher methodMatcher;
public void setClassFilter(ClassFilter classFilter){
this.classFilter = classFilter;
}
public void setMethodMatcher(MethodMatcher methodMatcher){
this.methodMatcher = methodMatcher;
}
public ClassFilter getClassFilter() {
// TODO Auto-generated method stub
return true;
}
public MethodMatcher getMethodMatcher() {
// TODO Auto-generated method stub
return methodMatcher;
}
}
public class CustomMethodMatch implements MethodMatcher {
private CustomAopConfig config;
public void setConfig(CustomAopConfig config){
this.config = config;
}
//过滤日志触发点
public boolean matches(Method arg0, Class arg1) {
// TODO Auto-generated method stub
Map aopConfigMap = config.getAopConfigMap();
//如果配置中有该类arg1的名称,同时在类信息下有该方法arg0的名称则返回true
if(aopConfigMap.containsKey(arg1.getName())){
AopClassTarget target = (AopClassTarget)aopConfigMap.get(arg1.getName());
Map methodMap = target.getMethods();
if(methodMap.containsKey(arg0.getName())){
return true;
}
}
return false;
}
public boolean isRuntime() {//如果是非静态的,需要设为true
// TODO Auto-generated method stub
return false;
}
//isRuntime()返回false不会调用该方法
public boolean matches(Method arg0, Class arg1, Object[] arg2) {
// TODO Auto-generated method stub
return false;
}
}
实现了自己的自动装配类,主要是考虑代理的bean与方法、参数等放在一个文件中,就不在这里再单独配置了
package com.jcy.support.aop.util;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import java.util.List;
/**
* 自动代理类,BEAN配置如下:
* <bean class="com.jcy.support.aop.util.CustomAopAutoProxy" init-method="setBeanNames">
<property name="interceptorNames">
<list>
<value>customAdvisor</value>
</list>
</property>
</bean>
* @author dingjun
*
*/
public class CustomAopAutoProxy extends BeanNameAutoProxyCreator {
private CustomAopConfig config;
public void setConfig(CustomAopConfig config){
this.config = config;
}
/**
* 载需要自动代理的BEAN的名称
* 必须在初始化 CustomAopAutoProxy后,马上被调用
*
*/
public void init(){
if(config!=null && !config.getBeanList().isEmpty()){
List list = config.getBeanList();
String[] str_arr = new String[list.size()];
config.getBeanList().toArray(str_arr);
super.setBeanNames(str_arr);
}
}
}
下面就是配置了
<bean id="config"
class="com.jcy.support.aop.util.CustomAopConfig"
scope="singleton"
destroy-method="destroy">
<constructor-arg><value>custom_aop_config.xml</value></constructor-arg>
</bean>
<bean id="customPointcut" class="com.jcy.support.aop.util.CustomPointcut">
<property name="classFilter" ref="classFilter"></property>
<property name="methodMatcher" ref="methodMatcher"></property>
</bean>
<bean id="classFilter" class="com.jcy.support.aop.util.CustomClassFilter"></bean>
<bean id="methodMatcher" class="com.jcy.support.aop.util.CustomMethodMatch" >
<property name="config" ref="config"></property>
</bean>
<bean id="customAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<constructor-arg ref="logAdvice"></constructor-arg>
<constructor-arg ref="customPointcut"></constructor-arg>
</bean>
<!—使用自动代理的好处就是不用再去修改原来业务系统bean的名字了。 -->
<bean class="com.jcy.support.aop.util.CustomAopAutoProxy" init-method="init">
<property name="config" ref="config"></property>
<!-- <property name="beanNames" >
<value>bean1,bean2,bean3</value>
</property>
这个参数由config中注入了,就不在这里设置了。
-->
<!-- 由于很多类没有实现自己的接口,此处应设为true,否则会报错,找不到类或方法之类的错误,会启用cglib ,
如果代理的类实现的自己的接口就不用配置该项。
-->
<property name="proxyTargetClass"><value>true</value></property>
<property name="interceptorNames">
<list>
<value>customAdvisor</value>
</list>
</property>
</bean>