码迷,mamicode.com
首页 > 编程语言 > 详细

Spring AOP

时间:2016-06-24 15:50:55      阅读:421      评论:0      收藏:0      [点我收藏+]

标签:


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);
	}
}


运行结果:

技术分享





Spring AOP

标签:

原文地址:http://blog.csdn.net/chuck_kui/article/details/51736018

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!