Spring面向切面编程AOP

1、什么是AOP

AOP,面向切面编程,是对OOP编程的补充。下面介绍下AOP中涉及的术语:

(1)Aspect切面

一个关注点的模块化,这个关注点可能横切多个对象。

(2)Jointpoint连接点

在程序执行过程中某个特定的点,比如添加一个日志处理方法,此方法的执行就是一个连接点。

(3)Pointcut切入点

与连接点是相互匹配的。

(4)Target目标

被一个或者多个切面所通知的对象,是被代理对象

(5)AOP Proxy AOP代理

AOP创建的对象。

(6)Weaving织入

把切面连接到其他应用逻辑的行为。

2、AOP作用

用来处理一些具有横切性质的系统性服务,比如日志管理、安全检查、事务管理等。

3、Spring对AOP的支持

Spring中的AOP代理由IoC容器负责生成和管理,因此AOP代理可以直接使用IoC容器中的其它Bean作为代理对象,即target。Spring使用Java动态代理创建AOP代理,需要注意的是,如果需要代理的类不是接口的时候,Spring会自动使用CGLIB来动态修改二进制码生成代理对象。

4、Spring中AOP的实现

(1)基于Annotation

(a)启用Spring对@AspectJ支持

<?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/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
 	
 	<!-- 启动@Aspectj支持 -->
 	<aop:aspectj-autoproxy />
</beans>
(b)定义一个切面Aspect

package cn.com.yy.aop;

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class LogHandlerAspect {

}
即使用注解@Aspect来声明该类是一个切面。

(c)前置通知---定义Before增强处理

package cn.com.yy.aop;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class LogHandlerAspect {
	
	// 匹配 cn.com.yy.service 包及其子包下所有类的login方法作为切入点  
	@Before("execution(public * cn.com.yy.service..*.login(**))")
	public void logPrint(){
		System.out.println("--print log info---");
	}
}
当匹配成功时,会首先指向logPrint方法,然后再执行所匹配的方法。

(d)最终通知---After增强处理

@After("execution(public * cn.com.yy.service..*.login(**))")
	public void close(){
		System.out.println("--close---");
	}
@After,不论一个方法是如何结束的,最终通知都会执行。

(e)后置通知--@AfterReturning

@AfterReturning("execution(public * cn.com.yy.service..*.login(**))")
	public void afterReturning(){
		System.out.println("---afterReturning---");
	}
该增强处理只有在匹配的方法成功完成后才会执行,这点不同于@After。

(f)异常通知--@AfterThrowing

@AfterThrowing("execution(public * cn.com.yy.service..*.login(**))")
	public void afterThrowing(){
		System.out.println("--afterThrowing method--");
	}
匹配方法发生异常时,才会织入。

当然,还有其他的增强通知。

注意:如果多个通知对应于同一个匹配表达式,此时可以抽取成公共切入点。

package cn.com.yy.aop;

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 LogHandlerAspect {
	//公共切入点
	@Pointcut("execution(public * cn.com.yy.service..*.login(**))")
	public void pubPointCut(){
	}
	
	//引用公共切入点
	@Before("pubPointCut")
	public void logPrint(){
		System.out.println("--print log info---");
	}
	//引用公共切入点
	@After("pubPointCut")
	public void close(){
		System.out.println("--close---");
	}
	//引用公共切入点
	@AfterReturning("pubPointCut")
	public void afterReturning(){
		System.out.println("---afterReturning---");
	}
	//引用公共切入点
	@AfterThrowing("pubPointCut")
	public void afterThrowing(){
		System.out.println("--afterThrowing method--");
	}
}

2)使用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/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
 	
 	<bean id="logAspect" class="cn.com.yy.aop.LogHandlerAspect"></bean>
 	<aop:config>
 			<!-- 定义一个切面 -->
 			<aop:aspect id="myAspect" ref="logAspect">
 				<!-- 前置通知 -->
 				<aop:before method="logPrint" pointcut="execution(public * cn.com.yy.service..*.login(**))"/>
 				<!-- 最终通知 -->
 				<aop:after method="close" pointcut="execution(public * cn.com.yy.service..*.login(**))"/>
 				<!-- 后置通知 -->
 				<aop:after-returning method="afterReturning" pointcut="execution(public * cn.com.yy.service..*.login(**))"/>
 				<!-- 异常通知 -->
 				<aop:after-throwing method="afterThrowing" pointcut="execution(public * cn.com.yy.service..*.login(**))"/>
 			</aop:aspect>
 			
 	</aop:config>
</beans>
如果一个切面中多个方法使用同一个匹配表达式,则可以提取公共,如下:

<aop:config>
 		<aop:aspect id="myAspect2" ref="logAspect">
 			<aop:pointcut expression="execution(public * cn.com.yy.service..*.login(**))" id="pubPointcut"/>
 			<aop:before method="logPrint" pointcut-ref="myPointcut"/>
 			<aop:after method="close" pointcut-ref="myPointcut"/>
 			<aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/>
 			<aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut"/>
 		</aop:aspect>
 	</aop:config>
当然,如果多个切面对应于同一个匹配表达式,可以提取公共到切面外。


你可能感兴趣的:(spring,AOP,AOP)