1, 使用代理增加日志, 也是基于最原始的办法
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class LoggingProxy { /* * 代理类, 基于接口 */ //要被代理的对象, 目标对象 private Icalculator target; //生成一个构造方法 public LoggingProxy(Icalculator target) { super(); this.target = target; } //应用通知. 并产生对象 public Icalculator getProxy() { Icalculator ica = null; //应用通知 //获得类加载器: ClassLoader, 类加载器在getClass()方法里面 ClassLoader cl = target.getClass().getClassLoader(); //获得class中所有方法的数组, 数组的内容一定要是接口.class Class[] cla= new Class[] {Icalculator.class}; //Class[] al = new Class[] {IJiSuanQi.class};//接口 //获得 InvocationHandler ih = new InvocationHandler() { @Override //调用invoke的时候就是实现一个切面编程 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //在这之前可以增加数据验证 Object obj = null; System.out.println(method.getName()+" 开始调用"); try { obj = method.invoke(target, args); } catch(Exception e) { System.out.println("异常通知: "+method.getName()); } System.out.println(method.getName()+" 结束调用"); return obj; } }; //产生代理对象, 引用了反射的jar包 ica = (Icalculator)Proxy.newProxyInstance(cl, cla, ih); return ica; } }
2, 使用AOP框架
配置文件
<!-- 前面定义的类class --> <bean id="cal" class="com.hanqi.Calculator"> </bean> <!-- 切面类 --> <bean id="la" class="com.hanqi.LoggingAspect"> </bean> <!-- 定义AOP --> <aop:config> <!-- 配置切点表达式, 被切入的方法 --> <!-- expression写对象必须是个接口被切入方法的名字, 如果要写所有的方法就用*号表示 --> <aop:pointcut expression="execution(* com.hanqi.Icalculator.*(int,int))" id="loggingpointcut"/> <!-- 配置切面和通知 --> <aop:aspect ref="la"> <!-- 方法前通知 --> <aop:before method="beforeMethod" pointcut-ref="loggingpointcut"/> <aop:after method="afterMethod" pointcut="execution(* com.hanqi.Icalculator.cheng(int,int))"/> <aop:after-throwing method="exceptionMethod" pointcut-ref="loggingpointcut" throwing="ex"/> <aop:after-returning method="returnMethod" pointcut-ref="loggingpointcut" returning="obj"/> </aop:aspect> </aop:config>
定义切面类
import java.util.Arrays; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; public class LoggingAspect { //切面类, 前置通知 public void beforeMethod(JoinPoint jp) { //获取方法名 String str = jp.getSignature().getName(); //返回一个参数列表 Object[] obj = jp.getArgs(); System.out.println("方法名 = "+str); System.out.println(Arrays.asList(obj)); System.out.println("这里是方法前的通知"); } public void afterMethod(JoinPoint jp) { System.out.println("这里是方法后的通知"); } //异常通知 public void exceptionMethod(JoinPoint jp,Exception ex) { System.out.println("异常信息"+ex); } //返回通知 public void returnMethod(JoinPoint jp,Object obj) { System.out.println("返回通知的结果: "+obj); } }
3, 使用注解的方式(标红的部分是注解), 一定记得写上返回值和, expression表达式
import org.springframework.stereotype.Component; @Component("cal") public class Calculator implements Icalculator { ...... 方法体 ...... }
import java.util.Arrays; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect @Component public class LoggingAspect { //切面类, 前置通知 @Before(value = "execution(* com.hanqi.Calculator.*(..))") public void beforeMethod(JoinPoint jp) { //获取方法名 String str = jp.getSignature().getName(); //返回一个参数列表 Object[] obj = jp.getArgs(); System.out.println("方法名 = "+str); System.out.println(Arrays.asList(obj)); System.out.println("这里是方法前的通知"); } //后置通知 @After("execution(* com.hanqi.Calculator.*(..))") public void afterMethod(JoinPoint jp) { System.out.println("这里是方法后的通知"); } //异常通知 @AfterThrowing(pointcut="execution(* com.hanqi.Calculator.*(..))", throwing="ex") public void exceptionMethod(JoinPoint jp,Exception ex) { System.out.println("异常信息"+ex); } //返回通知 @AfterReturning(pointcut="execution(* com.hanqi.Calculator.*(..))", returning="obj") public void returnMethod(JoinPoint jp,Object obj) { System.out.println("返回通知的结果: "+obj); } }
注解的配置文件
<?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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <!-- 使用注解的方式 --> <!-- 扫描器 --> <context:component-scan base-package="com.hanqi"></context:component-scan> <!-- 启用AOP注解 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>