关于AOP使用的自我总结

AOP 面向切面编程

IOC为基础、对OOP补充与完善。

背景

OOP是通过封装、继承和多态等概念来建立一种对象层次结构,引入公共行为,当我们需要从离散的对象中引入公共行为时,就会导致代码的冗余,也无法拥有灵活性。例如:日志记录、异常通知、事务处理、权限认证等。

AOP却相反,它利用“横切”(抽出散布在各处的公共行为)技术,将影响多个类的公共行为封装,即切面,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

概念

1.通知(Advice):
通知定义了切面要发生的“故事”和时间。

2.连接点(Joinpoint):
程序能够应用通知的一个“时机”,例如方法被调用时、异常被抛出时等等。

3.切入点(Pointcut)
定义切面发生的地点,例如某个类或方法的名称

4.切面(Aspect)
通知和切入点共同组成了切面:时间、地点和要发生的“故事”

5.引入(Introduction)
引入允许我们向现有的类添加新的方法和属性(Spring提供了一个方法注入的功能)6.目标(Target)
被一个或者多个切面所通知的对象。

7.代理(proxy)
Spring AOP中有两种代理方式,JDK动态代理和CGLIB代理。默认情况下,TargetObject实现了接口时,则采用JDK动态代理,强制使用CGLIB代理需要将<aop:config>proxy-target-class属性设为true

8.织入(Weaving)
把切面应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机:
(1)编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器
(2)类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码
(3)运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理应该是使用了JDK的动态代理技术

Spring AOP使用

1.基于XML 配置方式

package my.test;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;

@Component
public class MyAspectOnXML
{
	public void before(JoinPoint joinPoint)
	{
		String className = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		System.out.println("调用前置通知的方法是:" + className + "."+ methodName + "()");
	}
	
	public void after()
	{
		System.out.println("最终通知:不管有没有正常执行,都执行");
	}
	
	public void afterReturn()
	{
		System.out.println("后置通知:只有正常返回的才执行");
	}
	
	public void afterThrowing()
	{
		System.out.println("异常抛出后通知");
	}
	
	public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
	{
		Object result = null;
		
		this.before(proceedingJoinPoint);
		
		try
		{
			result = proceedingJoinPoint.proceed();
			this.afterReturn();
		}
		catch (Throwable e)
		{
			this.afterThrowing();
			
			throw e;
		}
		finally
		{
			this.after();
		}
		
		return result;
	}
}

<aop:config>
	<aop:aspect id="aspect" ref="myAspectOnXML"/>
	<aop:pointcut id="allMethod"  expression="execution(* com.my.(..))"/>    
       	<aop:before method="before" pointcut-ref="allMethod" />    
        <aop:after-returning method="afterReturn" pointcut-ref="allMethod"/>    
        <aop:after method="after" pointcut-ref="allMethod"/>    
        <aop:after-throwing method="afterThrowing" pointcut-ref="allMethod"/>
</aop:config>

 

2.基于注解

package my.test;

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.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class MyAspectOnAnno
{
	@Pointcut("execution(* my.test.myController.*(..))")
	private void method()
	{
		
	}
	@Before("method()")
	public void before(JoinPoint joinPoint)
	{
		String className = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		System.out.println("调用前置通知的方法是:" + className + "."+ methodName + "()");
	}
	
	@After("method()")
	public void after()
	{
		System.out.println("最终通知:不管有没有正常执行,都执行");
	}
	
//	@AfterReturning("method()")
	@AfterReturning(pointcut="execution(* my.test.myController.*(..))",returning="result")
	public void afterReturn(Object result)
	{
		System.out.println("后置通知:只有正常返回的才执行 :" + (result == null ? "" : (String)result));
	}
	
	@AfterThrowing("method()")
	public void afterThrowing()
	{
		System.out.println("异常抛出后通知");
	}
	//@Around("method()")
	public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
	{
		Object result = null;
		
		this.before(proceedingJoinPoint);
		
		try
		{
			result = proceedingJoinPoint.proceed();
			this.afterReturn("");
		}
		catch (Throwable e)
		{
			this.afterThrowing();
			
			throw e;
		}
		finally
		{
			this.after();
		}
		
		return result;
	}

}

<aop:aspectj-autoproxy/>

注意

1)任何通知(Advice)方法可以将第一个参数定义为org.aspectj.lang.JoinPoint类型。JoinPoint接口提供了一系列有用的方法, 比如getArgs()(返回方法参数)、getThis()(返回代理对象)、getTarget()(返回目标)、getSignature()(返回正在被通知的方法相关信息)和toString()(打印出正在被通知的方法的有用信息。

2)Indeed your controller and your aspects should be in the same spring context

3)参考链接

http://pandonix.iteye.com/blog/336873/

http://developer.51cto.com/art/201105/262534_all.htm

http://blog.csdn.net/moreevan/article/details/11977115

http://blog.csdn.net/udbnny/article/details/5870076

http://www.cnblogs.com/davidwang456/p/4121765.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值