Spring学习之路(4)——AOP

为什么要使用AOP?

AOP是面向对象编程(OOP)的一种补充,目前已成为一种比较成熟的编程方式。

在传统的业务处理代码中,通常都会进行事务处理、日志记录等操作。虽然使用OOP可以通过组合或者继承的方式来达到代码的重用,但如果要实现某个功能(如日志记录),同样的代码仍然会分散到各个方法中。这样,如果想要关闭某个功能,或者对其进行修改,就必须要修改所有的相关方法。这不但增加了开发人员的工作量,而且提高了代码的出错率。

为了解决这一问题,AOP思想随之产生。AOP采用横向抽取机制,将分散在各个方法的重复代码提取出来,然后在程序编译或运行时,再将这些提取出来的代码应用到需要执行的地方。这种采用横向抽取机制的方式,采用传统的OOP思想显然是无法办到的,因为OOP只能实现父子关系的纵向的重用。虽然AOP是一种新的编程思想,但却不是OOP的替代品,它只是OOP的延伸和补充。

AOP的使用,使开发人员在编写业务逻辑时可以专心于核心业务,而不必过多地关注于其他业务逻辑的实现这不但提高了开发效率,而且增强了代码的可维护性。

 AOP中的名词概念

Aspect(切面):指横切性关注点的抽象即为切面,与类相似,只是两者的关注点不同,类是对物体特征的抽象,而切面是对横切面关注点的抽象。

JoinPoint(连接点):连接点是指那些被拦截到的点,spring中这些点指的是方法。

Pointcut(切入点):切入点是指我们要对那些JoinPoint进行拦截的定义。

Advice(通知):通知是指拦截到JoinPoint之后要做的事情,分为前置通知、后置通知、异常通知,最终通知、环绕通知。

前置通知和后置通知一个是在连接点之前执行,一个是在连接点退出的时候执行。异常通知是方法抛出异常退出时执行的逻辑。环绕通知是包围连接点退出的时候执行的逻辑。

AOP注解方式编程的步骤

  1. 定义一个切面类    @Aspect注解
  2. 定义@Pointcut切点,即定义一个方法,指定拦截项目中的那些方法
  3. 定义五中类型中的哪一种通知,即定义了一个方法,表示切点拦截到了方法后,执行什么功能
  4. beans.xml中添加<aop:aspectj-autoproxy></aop:aspectj-autoproxy>标签,支持aop的注解
package cn.sdut.aop;

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.stereotype.Component;

/**
 * 切面类
 * @author DELL
 *
 */

@Component //组件注解
@Aspect //注解切面类
public class AspectLog {

	//注解切入点作用于cn.sdut.service包下所有的类的方法
	@Pointcut(value="execution(* cn.sdut.service.*.*(..))")
	private void pointCut() {
		
	}
	
	//注解前置通知
	@Before(value="pointCut()")
	public void beforeLog(JoinPoint joinPoint) {
		System.out.println(joinPoint.getSignature().getDeclaringTypeName()+"."
	+joinPoint.getSignature().getName()+" is called.. before");
	}
	
	//注解后置通知
	@After(value="pointCut()")
	public void afterLog(JoinPoint joinPoint) {
		System.out.println(joinPoint.getSignature().getDeclaringTypeName()+"."
	+joinPoint.getSignature().getName()+" is called.. after");
	}
	
	//返回注解通知
	@AfterReturning(value="pointCut()")
	public void afterReturningLog(JoinPoint joinPoint) {
		System.out.println(joinPoint.getSignature().getDeclaringTypeName()+"."+
	joinPoint.getSignature().getName()+" ar is called.. return");
	}
	
	//环绕通知
	@Around(value="pointCut()")
	public Object AroundLog(ProceedingJoinPoint point) throws Throwable {
		System.out.println(point.getSignature().getDeclaringTypeName()+"."+
				point.getSignature().getName()+" ar is called.. start");
		Object object = point.proceed();
		System.out.println(point.getSignature().getDeclaringTypeName()+"."+
				point.getSignature().getName()+" ar is called.. end");
		return object;
	}
	
	//异常通知
	@AfterThrowing(value="pointCut()")
	public void afterThrowingLog(JoinPoint joinPoint) {
		System.out.println(joinPoint.getSignature().getDeclaringTypeName()+"."+
	joinPoint.getSignature().getName()+" ar is called.. throwing");
	}
}

AOP的xml方式配置

  • 定义切面类,编写切面类中的方法
  • beans.xml中配置aop信息

<aop:config>
                <aop:aspect id="myAspect" ref="aspectLog">
                    <aop:pointcut id="mypointcut" expression="execution(* cn.sdut.dao.*.*(..))" />
                    <aop:before method="beforeLog" pointcut-ref="mypointcut"/>
                    <aop:after method="afterLog" pointcut-ref="mypointcut"/>
                    <aop:after-returning method="afterReturningLog" pointcut-ref="mypointcut"/>
                    <aop:around method="aroundLog" pointcut-ref="mypointcut"/>
                    <aop:after-throwing method="afterThrowingLog" pointcut-ref="mypointcut"/>
                </aop:aspect>
            </aop:config>

 

ref指向的是切面类首字母小写 。

 

发布了157 篇原创文章 · 获赞 175 · 访问量 13万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 数字50 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览