今天学习了下spring中的切面编程;结合之前看过的视频。整合一下思路:
基本类:
接口:
public interface ArithmeticCalculator { int add(int i, int j); int sub(int i, int j); int mul(int i, int j); int div(int i, int j); }
接口的实现:
import org.springframework.stereotype.Component; @Component("arithmeticCalculator") public class ArithmeticCalculatorImpl implements ArithmeticCalculator { @Override public int add(int i, int j) { int result = i + j; return result; } @Override public int sub(int i, int j) { int result = i - j; return result; } @Override public int mul(int i, int j) { int result = i * j; return result; } @Override public int div(int i, int j) { int result = i / j; return result; } }
切面声明:
import java.util.Arrays; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * AOP 的 helloWorld * 1. 加入 jar 包 * com.springsource.net.sf.cglib-2.2.0.jar * com.springsource.org.aopalliance-1.0.0.jar * com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar * spring-aspects-4.0.0.RELEASE.jar * * 2. 在 Spring 的配置文件中加入 aop 的命名空间。 * * 3. 基于注解的方式来使用 AOP * 3.1 在配置文件中配置自动扫描的包: <context:component-scan base-package="com.atguigu.spring.aop"></context:component-scan> * 3.2 加入使 AspjectJ 注解起作用的配置: <aop:aspectj-autoproxy></aop:aspectj-autoproxy> * 为匹配的类自动生成动态代理对象. * * 4. 编写切面类: * 4.1 一个一般的 Java 类 * 4.2 在其中添加要额外实现的功能. * * 5. 配置切面 * 5.1 切面必须是 IOC 中的 bean: 实际添加了 @Component 注解 * 5.2 声明是一个切面: 添加 @Aspect * 5.3 声明通知: 即额外加入功能对应的方法. * 5.3.1 前置通知: @Before("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(int, int))") * @Before 表示在目标方法执行之前执行 @Before 标记的方法的方法体. * @Before 里面的是切入点表达式: * * 6. 在通知中访问连接细节: 可以在通知方法中添加 JoinPoint 类型的参数, 从中可以访问到方法的签名和方法的参数. * * 7. @After 表示后置通知: 在方法执行之后执行的代码. */ //通过添加 @Aspect 注解声明一个 bean 是一个切面! @Aspect @Component//注解 public class LoggingAspect { @Pointcut("execution(* com.atguigu.spring.aop.*.*(..))") public void pointcount(){} @Before("pointcount()") public void beforeMethod(JoinPoint joinPoint){ String methodName = joinPoint.getSignature().getName(); Object [] args = joinPoint.getArgs(); System.out.println("ASPECTJ The method " + methodName + " begins with " + Arrays.asList(args)); } @After("pointcount())") public void afterMethod(JoinPoint joinPoint){ String methodName = joinPoint.getSignature().getName(); System.out.println("ASPECTJ The method " + methodName + " ends"); } }
测试:
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { // ArithmeticCalculator arithmeticCalculator = new ArithmeticCalculatorImpl(); // // arithmeticCalculator = // new ArithmeticCalculatorLoggingProxy(arithmeticCalculator).getLoggingProxy(); // // int result = arithmeticCalculator.add(11, 12); // System.out.println("result:" + result); // // result = arithmeticCalculator.div(21, 3); // System.out.println("result:" + result); ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-aop.xml"); ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator) ctx.getBean("arithmeticCalculator"); System.out.println(arithmeticCalculator.getClass().getName()); int result = arithmeticCalculator.add(11, 12); System.out.println("result:" + result); result = arithmeticCalculator.div(21, 3); System.out.println("result:" + result); } }
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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 自动扫描的包 --> <context:component-scan base-package="com.atguigu.spring.aop"></context:component-scan> <!-- 使 AspectJ 的注解起作用 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
xml配置文件方式:
第一个切面:
import java.util.Arrays; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; public class LoggingAspect { public void beforeMethod(JoinPoint joinPoint){ String methodName = joinPoint.getSignature().getName(); Object [] args = joinPoint.getArgs(); System.out.println("The method " + methodName + " begins with " + Arrays.asList(args)); } public void afterMethod(JoinPoint joinPoint){ String methodName = joinPoint.getSignature().getName(); System.out.println("The method " + methodName + " ends"); } public void afterReturning(JoinPoint joinPoint, Object result){ String methodName = joinPoint.getSignature().getName(); System.out.println("The method " + methodName + " ends with " + result); } public void afterThrowing(JoinPoint joinPoint, Exception e){ String methodName = joinPoint.getSignature().getName(); System.out.println("The method " + methodName + " occurs excetion:" + e); } @Around("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))") public Object aroundMethod(ProceedingJoinPoint pjd){ Object result = null; String methodName = pjd.getSignature().getName(); try { //前置通知 System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs())); //执行目标方法 result = pjd.proceed(); //返回通知 System.out.println("The method " + methodName + " ends with " + result); } catch (Throwable e) { //异常通知 System.out.println("The method " + methodName + " occurs exception:" + e); throw new RuntimeException(e); } //后置通知 System.out.println("The method " + methodName + " ends"); return result; } }
第二个切面:
import java.util.Arrays; import org.aspectj.lang.JoinPoint; public class VlidationAspect { public void validateArgs(JoinPoint joinPoint){ System.out.println("-->validate:" + Arrays.asList(joinPoint.getArgs())); } }
测试类:
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-xml.xml"); ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator) ctx.getBean("arithmeticCalculator"); System.out.println(arithmeticCalculator.getClass().getName()); int result = arithmeticCalculator.add(1, 2); System.out.println("result:" + result); result = arithmeticCalculator.div(1000, 2); System.out.println("result:" + result); } }
配置文件清单:
<?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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <!-- 配置 bean --> <bean id="arithmeticCalculator" class="com.atguigu.spring.aop.xml.ArithmeticCalculatorImpl"></bean> <!-- 配置切面的 bean. --> <bean id="loggingAspect" class="com.atguigu.spring.aop.xml.LoggingAspect"></bean> <bean id="vlidationAspect" class="com.atguigu.spring.aop.xml.VlidationAspect"></bean> <!-- 配置 AOP --> <aop:config> <!-- 配置切点表达式 --> <aop:pointcut expression="execution(* com.atguigu.spring.aop.xml.ArithmeticCalculator.*(int, int))" id="pointcut"/> <!-- 配置切面及通知 --> <aop:aspect ref="loggingAspect" order="2"> <aop:before method="beforeMethod" pointcut-ref="pointcut"/> <aop:after method="afterMethod" pointcut-ref="pointcut"/> <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/> <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/> <!-- <aop:around method="aroundMethod" pointcut-ref="pointcut"/> --> </aop:aspect> <aop:aspect ref="vlidationAspect" order="1"><!--order越小,优先级越高--> <aop:before method="validateArgs" pointcut-ref="pointcut"/> </aop:aspect> </aop:config> </beans>
第三:代理的方式:(不推荐使用)
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; public class ArithmeticCalculatorLoggingProxy { //要代理的对象 private ArithmeticCalculator target; public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target) { super(); this.target = target; } //返回代理对象 public ArithmeticCalculator getLoggingProxy(){ ArithmeticCalculator proxy = null; ClassLoader loader = target.getClass().getClassLoader(); Class [] interfaces = new Class[]{ArithmeticCalculator.class}; InvocationHandler h = new InvocationHandler() { /** * proxy: 代理对象。 一般不使用该对象 * method: 正在被调用的方法 * args: 调用方法传入的参数 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); //打印日志 System.out.println("[before] The method " + methodName + " begins with " + Arrays.asList(args)); //调用目标方法 Object result = null; try { //前置通知 result = method.invoke(target, args); //返回通知, 可以访问到方法的返回值 } catch (NullPointerException e) { e.printStackTrace(); //异常通知, 可以访问到方法出现的异常 } //后置通知. 因为方法可以能会出异常, 所以访问不到方法的返回值 //打印日志 System.out.println("[after] The method ends with " + result); return result; } }; /** * loader: 代理对象使用的类加载器。 * interfaces: 指定代理对象的类型. 即代理代理对象中可以有哪些方法. * h: 当具体调用代理对象的方法时, 应该如何进行响应, 实际上就是调用 InvocationHandler 的 invoke 方法 */ proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h); return proxy; } }
public class ArithmeticCalculatorLoggingImpl implements ArithmeticCalculator { @Override public int add(int i, int j) { System.out.println("The method add begins with [" + i + "," + j + "]"); int result = i + j; System.out.println("The method add ends with " + result); return result; } @Override public int sub(int i, int j) { System.out.println("The method sub begins with [" + i + "," + j + "]"); int result = i - j; System.out.println("The method sub ends with " + result); return result; } @Override public int mul(int i, int j) { System.out.println("The method mul begins with [" + i + "," + j + "]"); int result = i * j; System.out.println("The method mul ends with " + result); return result; } @Override public int div(int i, int j) { System.out.println("The method div begins with [" + i + "," + j + "]"); int result = i / j; System.out.println("The method div ends with " + result); return result; } }
时间: 2024-10-20 09:17:50