场景说明:在开发调试时,总是需要打断点来看哪个方法错误了,哪些参数传错了,在很多情况下如果直接能从日志中拿到是执行了哪个类的哪个方法,并且知道方法参数情况,可能会大大减少调试时间,一种做法是在相应的方法上加上日志,这样会非常的烦人,重复工作很多,而且为了完全,可能在上线的时候还要去除,在这种场景下使用AOP是非常合适的,AOP可以达到一次配置,到处使用的效果。
1.xml配置方式:
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<bean id="aopHandler" class="com.shidebin.mongodb.springAop.AopConfiguration"></bean>
<bean id="windows98" class="com.shidebin.mongodb.springAop.Windows98"/>
<bean id="windows2000" class="com.shidebin.mongodb.springAop.Windows2000"/>
<bean id="windows7" class="com.shidebin.mongodb.springAop.Windows7"/>
<bean id="computer" class="com.shidebin.mongodb.springAop.Computer">
<constructor-arg ref="windows7" />
</bean>
<aop:config>
<aop:aspect ref="aopHandler">
<!--execution(* *(..)) 匹配所有的类中的所有方法,这个表达式各参数为:修饰词 返回值 包名.方法名(参数列表) -->
<aop:pointcut id="aopAdvice" expression="execution(* *(..))"/>
<aop:before method="beforeAdvice" pointcut-ref="aopAdvice"/>
<aop:after method="AftereAdvice" pointcut-ref="aopAdvice"/>
<aop:after-returning method="AfterReturnAdvice" pointcut-ref="aopAdvice" returning="result"/>
<aop:around method="aroundAdvice" pointcut-ref="aopAdvice"/>
<aop:after-throwing method="afterThrowingAdvice" pointcut-ref="aopAdvice" throwing="e"/>
</aop:aspect>
</aop:config>
</beans>
aop处理类:
package com.shidebin.mongodb.springAop;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.JSONToken;
public class AopConfiguration {
Logger logger = null;
void beforeAdvice(JoinPoint point) {
Object[] args = point.getArgs();
Map<String,Object> argMap = new HashMap<String,Object>();
for(int i = 0; i<args.length;i++) {
argMap.put("arg"+i, args[i]);
}
Signature signature = point.getSignature();
logger = Logger.getLogger(signature.getDeclaringType());
//方法名
String name = signature.getName();
String jsonString = JSONObject.toJSONString(argMap);
logger.info("调用方法:<"+name+">\n方法参数为:\n"+jsonString);
}
void AftereAdvice(JoinPoint point) {
//方法名
Signature signature = point.getSignature();
logger = Logger.getLogger(signature.getDeclaringType());
String name = signature.getName();
logger.info("方法:<"+name+">调用完成");
}
void AfterReturnAdvice(JoinPoint point, Object result) {
// 方法名
Signature signature = point.getSignature();
logger = Logger.getLogger(signature.getDeclaringType());
String name = signature.getName();
logger.info("调用方法:<" + name + ">的返回值为:"+JSONObject.toJSONString(result));
}
void afterThrowingAdvice(JoinPoint point,Exception e) {
Object[] args = point.getArgs();
Map<String,Object> argMap = new HashMap<String,Object>();
for(int i = 0; i<args.length;i++) {
argMap.put("arg"+i, args[i]);
}
Signature signature = point.getSignature();
logger = Logger.getLogger(signature.getDeclaringType());
//方法名
String name = signature.getName();
String jsonString = JSONObject.toJSONString(argMap);
logger.info("调用方法:<"+name+">\n方法参数为:\n"+jsonString+"发生异常,异常如下:\n");
e.printStackTrace();
}
//环绕是before和after的功能相加
Object aroundAdvice(ProceedingJoinPoint point) throws Throwable {
Object[] args = point.getArgs();
Map<String,Object> argMap = new HashMap<String,Object>();
for(int i = 0; i<args.length;i++) {
argMap.put("arg"+i, args[i]);
}
Signature signature = point.getSignature();
logger = Logger.getLogger(signature.getDeclaringType());
//方法名
String name = signature.getName();
String jsonString = JSONObject.toJSONString(argMap);
logger.info("调用方法:<"+name+">\n方法参数为:\n"+jsonString);
Object proceed = point.proceed();
logger.info("方法:<"+name+">调用完成");
return proceed;
}
}
测试类:
package com.shidebin.mongodb.springAop;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.shidebin.mongodb.springAop2.Computer;
import com.shidebin.mongodb.springAop2.User;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class AopAnnotationTest {
@Autowired
public Computer computer;
@Test
public void test() {
User user = new User();
user.setUsername("shidebin");
user.setCountry("china");
user.setAge(29);
computer.work(user,"win7");
System.out.println("test method runing");
}
@Test
public void testReturn() {
User user = new User();
user.setUsername("shidebin");
user.setCountry("china");
user.setAge(29);
computer.getWork(user);
}
@Test
public void testException() {
User user = null;
computer.generateThrow(user);
}
}
还有其他相关类请看git项目:https://github.com/shidebin/spring
2.注解方式:
applicationContext2.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:cache="http://www.springframework.org/schema/cache" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.shidebin.mongodb.springAop2"></context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>
AOP处理类:
package com.shidebin.mongodb.springAop2;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.JSONToken;
@Aspect
@Component
public class AopConfiguration {
Logger logger = null;
//修饰词任意 com.shidebin包及其子包下的方法参数任意的方法
@Before("execution(* com.shidebin..*.*(..))")
void beforeAdvice(JoinPoint point) {
Object[] args = point.getArgs();
Map<String,Object> argMap = new HashMap<String,Object>();
for(int i = 0; i<args.length;i++) {
argMap.put("arg"+i, args[i]);
}
Signature signature = point.getSignature();
logger = Logger.getLogger(signature.getDeclaringType());
//方法名
String name = signature.getName();
String jsonString = JSONObject.toJSONString(argMap);
logger.info("调用方法:<"+name+">\n方法参数为:\n"+jsonString);
}
//修饰词public 任意包下的方法参数任意的方法
@After("execution(public * *(..))")
void AftereAdvice(JoinPoint point) {
//方法名
Signature signature = point.getSignature();
logger = Logger.getLogger(signature.getDeclaringType());
String name = signature.getName();
logger.info("方法:<"+name+">调用完成");
}
//修饰词public 任意包下的方法参数任意的方法
@AfterReturning(value = "execution(public * *(..))",returning="result")
void AfterReturnAdvice(JoinPoint point, Object result) {
// 方法名
Signature signature = point.getSignature();
logger = Logger.getLogger(signature.getDeclaringType());
String name = signature.getName();
logger.info("调用方法:<" + name + ">的返回值为:"+JSONObject.toJSONString(result));
}
//修饰词任意 任意包下的方法参数任意的方法
@AfterThrowing(value = "execution(** *(..))",throwing="e")
void afterThrowingAdvice(JoinPoint point,Exception e) {
Object[] args = point.getArgs();
Map<String,Object> argMap = new HashMap<String,Object>();
for(int i = 0; i<args.length;i++) {
argMap.put("arg"+i, args[i]);
}
Signature signature = point.getSignature();
logger = Logger.getLogger(signature.getDeclaringType());
//方法名
String name = signature.getName();
String jsonString = JSONObject.toJSONString(argMap);
logger.info("调用方法:<"+name+">\n方法参数为:\n"+jsonString+"发生异常,异常如下:\n");
e.printStackTrace();
}
//修饰词public 任意包下的方法参数任意的方法
@Around("execution(public * *(..))")
Object aroundAdvice(ProceedingJoinPoint point) throws Throwable {
Object[] args = point.getArgs();
Map<String,Object> argMap = new HashMap<String,Object>();
for(int i = 0; i<args.length;i++) {
argMap.put("arg"+i, args[i]);
}
Signature signature = point.getSignature();
logger = Logger.getLogger(signature.getDeclaringType());
//方法名
String name = signature.getName();
String jsonString = JSONObject.toJSONString(argMap);
logger.info("调用方法:<"+name+">\n方法参数为:\n"+jsonString);
Object proceed = point.proceed();
logger.info("方法:<"+name+">调用完成");
return proceed;
}
}
测试类:
package com.shidebin.mongodb.springAop;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.shidebin.mongodb.springAop2.Computer;
import com.shidebin.mongodb.springAop2.User;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class AopAnnotationTest {
@Autowired
public Computer computer;
@Test
public void test() {
User user = new User();
user.setUsername("shidebin");
user.setCountry("china");
user.setAge(29);
computer.work(user,"win7");
System.out.println("test method runing");
}
@Test
public void testReturn() {
User user = new User();
user.setUsername("shidebin");
user.setCountry("china");
user.setAge(29);
computer.getWork(user);
}
@Test
public void testException() {
User user = null;
computer.generateThrow(user);
}
}
还有其他相关类请看git项目:https://github.com/shidebin/spring
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.shidebin.mongodb</groupId>
<artifactId>spring-aop</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-aop</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<springversion>4.1.8.RELEASE</springversion>
<mybatis.version>3.2.6</mybatis.version>
<fastjson.version>1.2.47</fastjson.version>
<log4j.version>1.2.17</log4j.version>
<slf4j.version>1.7.7</slf4j.version>
</properties>
<dependencies>
<!-- spring包引入 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${springversion}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${springversion}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springversion}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${springversion}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springversion}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${springversion}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springversion}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${springversion}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${springversion}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.11</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>
</project>
此例子实现了调用方法前参数,返回值,调用方法后,抛出异常时的日志打印。