SSH学习:Spring AOP系列学习

Spring系列学习之Spring AOP
1.何谓AOP?
    aop是开发中面向切面编程的一种思想
    AOP与OOP的对比:OOP是面向对象编程的一种思想。即模拟现实世界模式一切皆对象;AOP是面前切面,即将过程横切处理的思想。
2.AOP的作用:
    1.提供了声明式的服务
    2.允许用户定义自己的切面
3.AOP常见的实现:
    1.Proxy方式实现AOP方式:
    2.CGLib方法实现AOP
    3.Spring AOP实现:注解aspect方式实现;基于配置文件方式实现
4.Spring AOP的实现:
    1.纯Java实现,无需特殊编译过程,不需要控制类加载层次;
    2.只支持方法执行连接点
    3.不是为了提供最完整的AOP实现,而是侧重提供一种AOP实现与Spring IOC容器之间的整合,用于帮助企业级应用提供常见问题的解决途径。
    4.Spring AOP默认使用标准的JavaSE动态代理作为AOP的代理器,使得所用的接口都可以被代理
    5.Spring AOP代理也可以使用CGLib代理

5.Spring AOP实现之基于注解aspect方式实现:
    1.代理对象业务代码:

package aop.aspect;

		public class Student {

			public String print(String name) {
				System.out.println(name + "print");
				return "hello word";
			}
			

		}

     2.注解实现的切面代码

package aop.aspect;

		import org.aspectj.lang.ProceedingJoinPoint;
		import org.aspectj.lang.annotation.After;
		import org.aspectj.lang.annotation.AfterReturning;
		import org.aspectj.lang.annotation.Around;
		import org.aspectj.lang.annotation.Aspect;
		import org.aspectj.lang.annotation.Before;
		import org.aspectj.lang.annotation.Pointcut;

		@Aspect
		public class StudnetInterceptor {

			/**
			 * 打印方法AOP
			 */
			@Pointcut("execution(* aspect.Student.print(..))")
			// @Pointcut("execution(*
			// com.jike.spring.chapter09.aop.aspect.Student.*(..))")
			public void printMethod() {
			}

			@Before("printMethod()")
			public void printBeforeAdvice() {
				System.out.println("printBeforeAdvice()!");
			}

			@AfterReturning(pointcut = "printMethod()", returning = "flag")
			public void printAfterAdvice(String flag) {
				System.out.println("printAfterAdvice()! " + flag);
			}

			@After("printMethod()")
			public void finallyAdvice() {
				System.out.println("finallyAdvice()!");
			}

			@Around("printMethod() && args(name)")
			public Object printAroundAdvice(ProceedingJoinPoint pjp, String name) throws Throwable {
				Object result = null;
				if (name.equals("whc"))
					pjp.proceed();
				else
					System.out.println("print()方法以及被拦截...");
				return result;
			}

		}

     3.测试代码:

public class Test {

			public static void main(String[] args) {
				ApplicationContext ctx = new ClassPathXmlApplicationContext("config/conf-aspect.xml");
				Student stu = (Student) ctx.getBean("stu");
				stu.print("whc");
			}

		}

 6.Spring AOP实现之aspect配置文件方式实现:

    1.被代理对象的业务事务代码

package aop.xml;

		public class Student {

			public String print(String name) {
				System.out.println(name + "print");
				return "hello word";
			}

		}

     2.基于配置文件实现的切面代码

package aop.xml;

		import org.aspectj.lang.ProceedingJoinPoint;
		import org.aspectj.lang.annotation.After;
		import org.aspectj.lang.annotation.AfterReturning;
		import org.aspectj.lang.annotation.Around;
		import org.aspectj.lang.annotation.Aspect;
		import org.aspectj.lang.annotation.Before;
		import org.aspectj.lang.annotation.Pointcut;

		/**
		 * Xml方式实现AOP切面
		 * 
		 * @author lilin
		 * @time 2016年5月27日 下午11:46:46
		 * @email [email protected]
		 * @blog http://gaosililin.iteye.com
		 * @school USC
		 * @team Geowind
		 */
		public class StudnetInterceptor {
			/**
			 * 打印方法AOP
			 */

			public void printMethod() {
			}

			public void printBeforeAdvice() {
				System.out.println("printBeforeAdvice()!");
			}

			public void printAfterAdvice(String name) {
				System.out.println("printAfterAdvice()! " + name);
			}

			public void finallyAdvice() {
				System.out.println("finallyAdvice()!");
			}

			public Object printAroundAdvice(ProceedingJoinPoint pjp, String name) throws Throwable {
				Object result = null;
				if (name.equals("whc"))
					pjp.proceed();
				else
					System.out.println("print()方法以及被拦截...");
				return result;
			}
		}

    3.测试代码:

package aop.xml;
			
		import org.springframework.context.ApplicationContext;
		import org.springframework.context.support.ClassPathXmlApplicationContext;

		public class Test {

			public static void main(String[] args) {
				ApplicationContext ctx = new ClassPathXmlApplicationContext("config/conf-xml.xml");
				Student stu = (Student) ctx.getBean("stu");
				stu.print("whc1");
			}

		}

     4.配置文件:

		<?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-3.1.xsd">
			<aop:aspectj-autoproxy />
			<bean id="stu" class="xml.Student"></bean>
			<bean id="interceptor" class="xml.StudnetInterceptor"></bean>

			<aop:config>
				<aop:aspect id="stuInterceptor" ref="interceptor">
					<aop:before pointcut="execution(* xml.Student.print(..))"
						method="printBeforeAdvice" />
					<aop:after-returning pointcut="execution(* xml.Student.print(..))"
						method="printAfterAdvice" />
					<aop:after pointcut="execution(* xml.Student.print(..))"
						method="finallyAdvice" />
					<aop:around pointcut="execution(* .xml.Student.print(..)) and args(name)"
						method="printAroundAdvice" />
				</aop:aspect>
			</aop:config>
		</beans>  

 7.Spring pointCut:



8.aop通知的执行的顺序:
    1.before:方法执行前
    2.around:环绕,方法执行之前,但是该方法第一个参数必须是ProceedingJoinPoint
    3.after-throwing:方法抛出异常之后
    4.after:方法执行之后
    5.after-returning:方法返回值之后

   示例代码:

     1.目标接口代码

package aop.aop;

public interface Foo {
	void play(String name);
}

    2.目标接口实现类代码

package aop.aop;

public class FooImpl implements Foo {

	@Override
	public void play(String name) {
		System.out.println("paling with " + name);
		throw new RuntimeException();
	}

}

   3.Interceptor类代码

package aop.aop;

import org.aspectj.lang.ProceedingJoinPoint;

/**
 * Xml配置实现通知
 * 
 * @author lilin
 * @time 2016年5月31日 下午12:36:52
 * @email [email protected]
 * @blog http://gaosililin.iteye.com
 * @school USC
 * @team Geowind
 */
public class FooInterceptor {
	/**
	 * 前置通知
	 */
	public void beforePaly() {
		System.out.println("FooInterceptor.beforePlay");
	}

	/**
	 * 后置通知
	 */
	public void afterPlay() {
		System.out.println("FooInterceptor.afterPlay");
	}

	/**
	 * 返回返回值后通知
	 */
	public void afterReturnning() {
		System.out.println("FooInterceptor.afterReturnning");
	}

	/**
	 * 抛出异常后通知
	 */
	public void throwExcetion() {
		System.out.println("FooInterceptor.throwExcetion");
	}

	/**
	 * 环绕通知 。第一个参数必须是ProceedingJoinPoint
	 * 
	 * @param pjp
	 * @param name
	 * @return
	 * @throws Throwable
	 */
	public Object printAroundAdvice(ProceedingJoinPoint pjp, String name) throws Throwable {
		Object result = null;
		if (name.equals("jing")) {
			try {
				result = pjp.proceed();
			} catch (Exception e) {
				System.out.println("诶呀,异常了");
			}
		} else {
			System.out.println("print()方法以及被拦截...");
		}
		return result;
	}

}

    4.测试类代码

package aop.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AopTest {

	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("config/introduce-introduce.xml");
		Foo foo = (Foo) context.getBean("foo");
			foo.play("jing");

	}

}

   5.配置文件

<?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-3.1.xsd">
	<aop:aspectj-autoproxy />
	<bean id="foo" class="aop.aop.FooImpl"></bean>
	<bean id="foointerceptor" class="aop.aop.FooInterceptor"></bean>
	<aop:config>
		<aop:aspect id="fooInterceptor" ref="foointerceptor">
			<aop:before method="beforePaly" pointcut="execution(* aop.aop.Foo.play(..) )" />
			<aop:after-returning method="afterReturnning"
				pointcut="execution(* aop.aop.Foo.play(..))" />
			<aop:after method="afterPlay" pointcut="execution(* aop.aop.Foo.play(..))" />
			<aop:around pointcut="execution(*  aop.aop.Foo.play(..)) and args(name)"
				method="printAroundAdvice" />
			<aop:after-throwing method="throwExcetion"
				pointcut="execution(* aop.aop.Foo.play(..))" />
		</aop:aspect>
	</aop:config>


</beans>  

   6.结果排序



 9.Advice  AOP增强

    Aop Advice中除了Introdutions引介增强外,其他的都是方法级别的增强,Introdutions引介增强是类级别的增强

  实现代码示例:

  1.增强对象的接口

package advice.advice;

/**
 * 增强对象的接口
 * 
 * @author lilin
 * @time 2016年5月31日 上午11:22:19
 * @email [email protected]
 * @blog http://gaosililin.iteye.com
 * @school USC
 * @team Geowind
 */
public interface Foo {

	void play(String name);

}

    2.增强的实现类

package advice.advice;

/**
 * 增强对象的实现类
 * 
 * @author lilin
 * @time 2016年5月31日 上午11:22:45
 * @email [email protected]
 * @blog http://gaosililin.iteye.com
 * @school USC
 * @team Geowind
 */
public class FooImpl implements Foo {

	@Override
	public void play(String name) {
		System.out.println("paling with " + name);
		// throw new RuntimeException();
	}

}

     3.前置增强

package advice.advice;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

/**
 * 前置增强
 * 
 * @author lilin
 * @time 2016年5月31日 上午11:27:42
 * @email [email protected]
 * @blog http://gaosililin.iteye.com
 * @school USC
 * @team Geowind
 */
public class BeforeAdvice implements MethodBeforeAdvice {

	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("BeforeAdvice.before:method " + method.getName() + " aug:" + args[0]);
	}

}

    5.后置增强

package advice.advice;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

/**
 * 后置增强
 * 
 * @author lilin
 * @time 2016年5月31日 上午11:23:42
 * @email [email protected]
 * @blog http://gaosililin.iteye.com
 * @school USC
 * @team Geowind
 */
public class AfterAdvice implements AfterReturningAdvice {

	@Override
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		System.out.println("AfterAdvice.afterReturning.  method:" + method.getName() + " arg:" + args[0]);
	}

}

    6.环绕增强

package advice.advice;

import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

/**
 * 环绕增强
 * 
 * @author lilin
 * @time 2016年5月31日 上午11:28:23
 * @email [email protected]
 * @blog http://gaosililin.iteye.com
 * @school USC
 * @team Geowind
 */
public class AroundAdvice implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation arg0) throws Throwable {
		Method method = arg0.getMethod();
		Object[] arguments = arg0.getArguments();
		// 环绕增强 前
		System.out.println("AroundAdvice.invoke.before  method:" + method.getName());
		// 放射方式调用目标方法
		Object proceed = arg0.proceed();
		// 环绕增强 后
		System.out.println("AroundAdvice.invoke.after  arg:" + arguments[0]);
		return proceed;
	}

}

    7.配置实现的配置文件

<?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:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<!-- 前置增强 -->
	<bean id="beforeAdvice" class="advice.advice.BeforeAdvice"></bean>
	<!-- 后置增强 -->
	<bean id="afterAdvice" class="advice.advice.AfterAdvice"></bean>
	<!-- 环绕增强 -->
	<bean id="aroundAdvice" class="advice.advice.AroundAdvice"></bean>
	<!-- 增强的对象 -->
	<bean id="target" class="advice.advice.FooImpl"></bean>



	<bean id="foo" class="org.springframework.aop.framework.ProxyFactoryBean"
		p:proxyInterfaces="advice.advice.Foo" p:target-ref="target"
		p:interceptorNames="beforeAdvice,afterAdvice,aroundAdvice" />


</beans>    

    8.测试代码

package advice.advice;

import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTest {

	public static void main(String[] args) {
		System.out.println("------xml配置风格实现之前增强-------");
		// ----------xml文件方式实现前置增强
		// 文件路径
		String path = "config/advice-advice.xml";
		// 加载配置文件
		ApplicationContext context = new ClassPathXmlApplicationContext(path);
		// 获取Bena对象
		Foo fooXml = (Foo) context.getBean("foo");
		// 调用play方法,查看是否实现前置通知
		fooXml.play("jing");
		System.out.println("------java风格实现之前增强-------");
		// ----- 实现接口方式实现前置增强
		// 创建增强的兑仓
		Foo foo = new FooImpl();
		// 创建前置增强的接口,切入点
		// 这里可以实现多个增强的切入点
		BeforeAdvice beforeAdvice = new advice.advice.BeforeAdvice();
		// 创建增强的代理器
		ProxyFactory proxyFactory = new ProxyFactory();
		// 设置代理目标
		proxyFactory.setTarget(foo);
		// 添加代理切口,可以添加多个切口
		proxyFactory.addAdvice(beforeAdvice);
		// 获取代理的器放回的对象
		Foo fooAdvice = (Foo) proxyFactory.getProxy();
		// 调用play方法,查看是否实现前置通知
		fooAdvice.play("gaosi");

		System.out.println("------后置增强增强-------");
		// -------后置增强
		// 切入后置增强的切入点
		AfterReturningAdvice afterReturningAdvice = new AfterAdvice();
		// 增加切入点
		proxyFactory.addAdvice(afterReturningAdvice);
		// 获取添加增强后的对象
		Foo afterAdviceFoo = (Foo) proxyFactory.getProxy();
		afterAdviceFoo.play("lg");

		System.out.println("-----环绕增强------");
		// 创建环绕增强的切面
		MethodInterceptor around = new AroundAdvice();
		// 添加环绕增强的切点
		proxyFactory.addAdvice(around);
		// 获取增加切点的对象
		Foo aroundFoo = (Foo) proxyFactory.getProxy();
		aroundFoo.play("jl");

	}

}

 运行结果



 10.Introdutions引介增强:
    Introdutions是允许一个切面声明一个实现指定的接口的通知对象,并且提供一个接口实现来代理这些对象。与advice的区别在于,advice是方法级别的增强,Introdutions是类级别的增强。

可以参考 introdutions增强
 

猜你喜欢

转载自gaosililin.iteye.com/blog/2302189