Spring AOP
来源:互联网 发布:描述性数据分析 编辑:程序博客网 时间:2024/06/06 18:22
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: 调用方法传入的参数 */@Overridepublic 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--> 3The 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 {@Overridepublic int add(int i, int j) {int result = i + j;return result;}@Overridepublic int sub(int i, int j) {int result = i - j;return result;}@Overridepublic int mul(int i, int j) {int result = i * j;return result;}@Overridepublic 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@Componentpublic 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@Componentpublic 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.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://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. 使用beanint 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 {@Overridepublic int add(int i, int j) {int result = i + j;return result;}@Overridepublic int sub(int i, int j) {int result = i - j;return result;}@Overridepublic int mul(int i, int j) {int result = i * j;return result;}@Overridepublic 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.xsdhttp://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. 使用beanint result = acImpl.add(3, 6);System.out.println( "result: " + result);result = acImpl.div(15,3);System.out.println( "result: " + result);}}
运行结果:
0 0
- AOP、Spring的AOP
- AOP--Spring AOP
- Spring AOP 嵌套AOP
- spring AOP
- Spring AOP
- Spring AOP
- spring aop
- Spring AOP
- spring AOP
- spring aop
- Spring aop
- Spring-AOP
- Spring AOP
- spring aop
- spring aop
- Spring AOP
- Spring AOP
- Spring Aop
- iOS蓝牙编程
- Yale CAS dotNet Client重定向循环问题
- CentOS7.0安装配置hadoop2.7.0
- 数据库可视化管理工具——Navicat
- Apriori算法
- Spring AOP
- 单片机 一位八段LED
- Spring 缓存
- pg_dump
- 鞍点
- zookeeper+dubbo+dubbo 的管理界面的入门案例
- JQuery读取本地Json文件
- FilenameFilter文件名过滤器使用实例
- 博客园博问闪存首页新随笔联系管理订阅 2011/6/2Java笔记之对象池1(commons-pool)