标签:
Spring—— AOP 的引子
动态代理模式
package com.baidu.aop.loggingProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; import com.baidu.aop.helloworld.ArithmeticCalculator; public class ArithmeticCalculatorloggingProxy { //要代理的对象 private ArithmeticCalculator target ; public ArithmeticCalculatorloggingProxy(ArithmeticCalculator target) { 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: 正在返回的那个代理对象。 一般情况下,在invoke 方法中都不使用该对象 * method: 正在被调用的方法 * args: 调用方法传入的参数 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // proxy.toString(); String methodName = method.getName(); //日志 System.out.println("The method " + methodName + "begins with " + Arrays.asList(args)); //执行方法 Object result = null; try { //前置通知 result = method.invoke(target, args); //返回通知,可以访问到方法的返回值 } catch (Exception e) { e.printStackTrace(); //异常通知: 可以访问到方法出现的异常 } //后置通知:因为方法可能会出异常,所以访问不到方法的返回值 //日志 System.out.println("The method " + methodName + "ends with " +result); return result; } }; proxy = (ArithmeticCalculator)Proxy.newProxyInstance(loader,interfaces,h); return proxy; } }
package TestSpringAOP; import com.baidu.aop.helloworld.ArithmeticCalculator; import com.baidu.aop.helloworld.ArithmeticCalculatorImpl; import com.baidu.aop.loggingProxy.ArithmeticCalculatorloggingProxy; public class TestSpringLoggingProxy { public static void main(String[] args) { ArithmeticCalculator target = new ArithmeticCalculatorImpl(); ArithmeticCalculator proxy = new ArithmeticCalculatorloggingProxy(target).getLoggingProxy(); int result = proxy.add(1, 2); System.out.println("--> " + result); result = proxy.div(4, 2); System.out.println("--> " + result); } }运行结果:
The method addbegins with [1, 2] The method addends with 3 --> 3 The method divbegins with [4, 2] The method divends with 2 --> 2
~~~~~~~~~~~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~示例如下~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
接口 ArithmeticCalculator.java
package com.baidu.aop.impl; 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); }接口的实现类 ArithmeticCalculatorImpl.java
package com.baidu.aop.impl; 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; } }切面
LoggingAspect.java
package com.baidu.aop.impl; import java.util.Arrays; import java.util.List; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; 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.core.annotation.Order; import org.springframework.stereotype.Component; /** * ①. 使用@Aspect 可以把一个类声明为一个切面: * ②. 需要把该类放入到IOC容器中 @Component * ③. 使用Order(value) 可以指定切面的优先级,值越小优先级越高 */ @Order(2) @Aspect @Component public class LoggingAspect { /** * 使用 @Pointcut 把一个方法声明为切入点表达式。一般的,该方法中再不需要添入其他的代码, * * 此方法的作用就是简各个通知,使用方法: * ①. 本类中: @Before("方法名") @Before("declareJoinPointExpression()") * ②. 本包中: @Before("类名.方法名") @Before("LoggingAspect.declareJoinPointExpression()") * ③. 外包中: @Before("包名.类名.方法名") @Before("com.baidu.aop.impl.LoggingAspect.declareJoinPointExpression()") */ @Pointcut("execution(int com.baidu.aop.impl.ArithmeticCalculator.*(..))") public void declareJoinPointExpression() {} /** * 声明该方法是一个前置通知:在目标方法开始之前执行 * @Before("execution(int com.baidu.aop.impl.ArithmeticCalculator.*(..))") */ @Before("declareJoinPointExpression()") public void beforeMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); List<Object> args = Arrays.asList(joinPoint.getArgs()); System.out.println("The method " + methodName + " begins with" + args ); } /** * 后置通知:在目标方法执行之后,执行的通知 :无论目标方法执行时,是否有异常发生,都会执行后置通知 * 在后置通知中,还不能访问目标方法执行的结果 * @After("execution(int com.baidu.aop.impl.ArithmeticCalculator.*(..))") */ @After("declareJoinPointExpression()") public void afterMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); System.out.println("The method " + methodName + " ends" ); } /** * 返回通知:在方法正常结束后执行的代码 。返回通知是可以访问到方法的返回值的 * @AfterReturning(value="execution(int com.baidu.aop.impl.ArithmeticCalculator.*(..))" ,returning="result") */ @AfterReturning(value="declareJoinPointExpression()" ,returning="result") public void afterReturning(JoinPoint joinPoint,Object result) { String methodName = joinPoint.getSignature().getName(); System.out.println("The method " + methodName + " ends with " + result ); } /** * 异常通知:在目标方法出现异常时才执行的代码.其 可以访问到异常对象,且可以指定在出现那种异常时,才执行通知代码 * 这里 的Exception 可以写为NullPointerException:表示只有在出现空指针异常时才执行 * @AfterThrowing(value="execution(int com.baidu.aop.impl.ArithmeticCalculator.*(..))" ,throwing="e") */ @AfterThrowing(value="declareJoinPointExpression()" ,throwing="e") public void afterThrowing(JoinPoint joinPoint,NullPointerException e) { String methodName = joinPoint.getSignature().getName(); System.out.println("The method " + methodName + " occurs excetion: " + e ); } // /** // * 环绕通知: 其是通知中最强的,但不是最常用的 // * ①. 其需要携带ProceedingJoinPoint 类的参数 // * ②. 其必须有返回值,返回值即为目标方法的返回值 // * // * 其类似于动态代理的全过程: ProceedingJoinPoint 类型的参数,可以决定是否执行目标方法 // * // * @param pjd // */ // @Around("execution(int com.baidu.aop.impl.ArithmeticCalculator.*(..))") // public Object aroundMethod(ProceedingJoinPoint pjd) { // System.out.println("aroundMethod: "); // // 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 excetion: " + e ); // throw new RuntimeException(e); // } // // // 后置通知 // System.out.println("The method " + methodName + " ends" ); // // return result; // } }为了配合演示切面的优先级而写验证切面:ValidationAspect .java
package com.baidu.aop.impl; import java.util.Arrays; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Order(1) @Aspect @Component public class ValidationAspect { @Before("LoggingAspect.declareJoinPointExpression()") public void validationArgs(JoinPoint joinPoint) { System.out.println("-->validationArgs.." + Arrays.asList(joinPoint.getArgs())); } }
bean: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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.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.0.xsd"> <!-- 配置自动扫描的包 --> <context:component-scan base-package="com.baidu.aop.impl"></context:component-scan> <!-- 使aspectj 注解起作用: 自动为匹配的类生成代理对象 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <!-- Build path is incomplete. Cannot find class file for org/aspectj/weaver/tools/PointcutDesignatorHandler --> </beans>
package com.baidu.aop.impl; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestSpringAOP { public static void main(String[] args) { // 1. 创建Spring 的IOC容器 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationcontext.xml"); //2. 从IOC 容器中获取bean 的实例 ArithmeticCalculator acImpl = (ArithmeticCalculator) ac.getBean("arithmeticCalculator"); //3. 使用bean int result = acImpl.add(3, 6); System.out.println( "result: " + result); result = acImpl.div(15,3); System.out.println( "result: " + result); } }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~ Spring AOP 用基于 XML 的配置声明切面~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
接口 ArithmeticCalculator.java
package com.baidu.aop.impl; 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); }接口的实现类 ArithmeticCalculatorImpl.java
package com.baidu.aop.impl; 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; } }
切面
LoggingAspect.java
package com.baidu.aop.xml; import java.util.Arrays; import java.util.List; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; public class LoggingAspect { public void beforeMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); List<Object> args = Arrays.asList(joinPoint.getArgs()); System.out.println("The method " + methodName + " begins with" + 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,NullPointerException e) { String methodName = joinPoint.getSignature().getName(); System.out.println("The method " + methodName + " occurs excetion: " + e ); } public Object aroundMethod(ProceedingJoinPoint pjd) { System.out.println("aroundMethod: "); 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 excetion: " + e ); throw new RuntimeException(e); } // 后置通知 System.out.println("The method " + methodName + " ends" ); return result; } }为了配合演示切面的优先级而写验证切面:ValidationAspect .java
package com.baidu.aop.xml; import java.util.Arrays; import org.aspectj.lang.JoinPoint; public class ValidationAspect { public void validationArgs(JoinPoint joinPoint) { System.out.println("-->validationArgs.." + Arrays.asList(joinPoint.getArgs())); } }bean:applicationcontext-xml.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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <!-- 配置 bean --> <bean id="arithmeticCalculator" class="com.baidu.aop.xml.ArithmeticCalculatorImpl"></bean> <!-- 配置切面的 bean. --> <bean id="loggingAspect" class="com.baidu.aop.xml.LoggingAspect"></bean> <bean id="validationAspect" class="com.baidu.aop.xml.ValidationAspect"> </bean> <!-- 配置 AOP --> <aop:config> <!-- 配置切点表达式 --> <aop:pointcut expression="execution(* com.baidu.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="validationAspect" order="1"> <aop:before method="validationArgs" pointcut-ref="pointcut"/> </aop:aspect> </aop:config> </beans>测试方法:TestSpringAOP_xml.java
package com.baidu.aop.xml; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestSpringAOP_xml { public static void main(String[] args) { // 1. 创建Spring 的IOC容器 ApplicationContext act = new ClassPathXmlApplicationContext("applicationcontext-xml.xml"); //2. 从IOC 容器中获取bean 的实例 ArithmeticCalculator acImpl = (ArithmeticCalculator) act.getBean("arithmeticCalculator"); //3. 使用bean int result = acImpl.add(3, 6); System.out.println( "result: " + result); result = acImpl.div(15,3); System.out.println( "result: " + result); } }
标签:
原文地址:http://blog.csdn.net/chuck_kui/article/details/51736018