springAOP有两种实现方式:
1、annotation注解方式
2、xml配置方式
依赖包有:
spring-aop.jar aspectjrtjar aspectjweaver.jar aopalliance.jar
其中,注解方式如下:
1、配置:
增加加入aop的xsd文件源:
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation增加:http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
加入@AspectJ标签
<aop:aspectj-autoproxy/>
自动帮我产生代理
2、使用注解方式新增aspect类
package com.aop;
import java.util.Arrays;
import java.util.Date;
import net.sf.json.JSONArray;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
/**
* 使用@Aspect 注解的类, Spring 将会把它当作一个特殊的Bean(一个切面),也就是
* 不对这个类本身进行动态代理
*/
@Component
@Aspect
public class AspectJLogger{
/**
* 必须为final String类型的,注解里要使用的变量只能是静态常量类型的
定义在service包里的任意方法的执行:
execution(* com.xyz.service.*.*(..))
*
*/
public static final String EDP = "execution(* com.web.*.*(..))";
@Before(EDP) //spring中Before通知
public void logBefore() {
System.out.println("logBefore:现在时间是:"+new Date());
}
@After(EDP) //spring中After通知
public void logAfter() {
System.out.println("logAfter:现在时间是:"+new Date());
}
@Around(EDP) //spring中Around通知
public Object logAround(ProceedingJoinPoint joinPoint) {
System.out.println("logAround开始:现在时间是:"+new Date()+ Arrays.toString(joinPoint.getArgs())); //方法执行前的代理处理
Object[] args = joinPoint.getArgs();
Object obj = null;
try {
obj = joinPoint.proceed(args);
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("logAround结束:现在时间是:"+new Date()); //方法执行后的代理处理
return obj;
}
}
就这样OK
下面介绍xml配置方式,这种方式的好处是能够分布式独立出切面出来,只需要配置好xml即可,供其他项目共用,避免了注解方式的对springIOC注解的依赖:
1、配置设置:
增加加入aop的xsd文件源:
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation增加:http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
配置引入切面bean:
<!-- 配置日志管理 -->
<bean id="LogManagerment" class="com.dan.common.aspect.LogManagerment">
</bean>
<aop:config>
<!--调用日志类-->
<aop:aspect id="b" ref="LogManagerment">
<!--配置在com.dan.modules.sample.dao包下所有的类的方法,在调用之前都会被拦截-->
<aop:pointcut id="logScope" expression="execution(* com.dan.modules.sample.dao.*.*(..))"/>
<!--在com.dan.modules.sample.dao包下所有的类的方法执行之前会调用LogManagerment中的before方法-->
<aop:before method="before" pointcut-ref="logScope"/>
<!--在com.dan.modules.sample.dao包下所有的类的方法执行之后会调用LogManagerment中的after方法-->
<aop:after method="after" pointcut-ref="logScope"/>
</aop:aspect>
</aop:config>
这样即可。
其中,该aspect实现如下:
package com.dan.common.aspect;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.aspectj.lang.JoinPoint;
import com.dan.common.utils.ModelClassHelper;
public class LogManagerment {
/**
* add操作执行之前执行的方法
*
* @param joinpoint包含action所有的相关配置信息和request等内置对象
* 。
* @throwsClassNotFoundException
* @throwsInstantiationException
* @throwsIllegalAccessException
*/
public void before(JoinPoint joinpoint) throws ClassNotFoundException,
InstantiationException, IllegalAccessException {
ModelClassHelper modelHelper = new ModelClassHelper();
// 此方法返回的是一个数组,数组中包括request以及ActionCofig等类对象
Object[] argumnets = joinpoint.getArgs();
for (int i = 0; i < argumnets.length; i++) {
// 打印实体类
String className = argumnets[i].toString(); // com.entity.User@eiid000
String modelName = className.substring(
className.lastIndexOf('.') + 1, className.indexOf('@'));
System.out.println("实体类:" + modelName);
// System.out.println("实体对应表:t_"+ modelName.toLowerCase());
System.out.println("==========================");
// 打印参数对象信息
Object obj = argumnets[i];
List fieldInfos = modelHelper.getFiledsInfo(obj);
for (Iterator iter = fieldInfos.iterator(); iter.hasNext();) {
Map map = (Map) iter.next();
System.out.println("字段类型:" + map.get("type"));
System.out.println("字段名称:" + map.get("name"));
System.out.println("字段值:" + map.get("value"));
System.out.println("==========================");
}
}
// 打印操作类型
String methodName = joinpoint.getSignature().getName();
System.out.println("方法名:" + methodName);
System.out.println("操作类型" + modelHelper.getOperationType(methodName));
System.out.println("被拦截方法调用之前调用此方法 before");
}
public void after(){
System.out.println("调用之后:"+new Date());
}
}
依赖的反射处理类:
package com.dan.common.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ModelClassHelper {
/**
* 通过反射Object,根据字段名称,获取字段值
*
* @param fieldName
* @param o
* @return
*/
private Object getFieldValueByName(String fieldName, Object o) {
try {
String firstLetter = fieldName.substring(0, 1).toUpperCase();
String getter = "get" + firstLetter + fieldName.substring(1);
Method method = o.getClass().getMethod(getter, new Class[] {});
Object value = method.invoke(o, new Object[] {});
return value;
} catch (Exception e) {
return null;
}
}
/**
* 通过反射Object,得到字段名称
*
* @param o
* @return
*/
private String[] getFiledName(Object o) {
Field[] fields = o.getClass().getDeclaredFields();
String[] fieldNames = new String[fields.length];
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i].getType());
fieldNames[i] = fields[i].getName();
}
return fieldNames;
}
/**
* 通过反射Object,获取对象信息:类型、名称、值
*
* @param o
* @return
*/
public List getFiledsInfo(Object o) {
Field[] fields = o.getClass().getDeclaredFields();
String[] fieldNames = new String[fields.length];
List list = new ArrayList();
Map infoMap = null;
for (int i = 0; i < fields.length; i++) {
infoMap = new HashMap();
infoMap.put("type", fields[i].getType().toString());
infoMap.put("name", fields[i].getName());
infoMap.put("value", getFieldValueByName(fields[i].getName(), o));
list.add(infoMap);
}
return list;
}
/**
* 根据方法名称,映射操作类型
*
* @param methodName
* @return
*/
public String getOperationType(String methodName) {
String type = "查询";
if (methodName.indexOf("add") > -1) {
type = "增加";
} else if (methodName.indexOf("del") > -1) {
type = "删除";
} else if (methodName.indexOf("update") > -1) {
type = "更新";
}
return type;
}
}
done.