spring中面向切面编程(Aop)

一、什么是AOP
AOP(Aspect-Oriented Programming, 面向切面编程): 是一种新的方法论, 是对传统 OOP(Object-Oriented Programming, 面向对象编程) 的补充。在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子。
AOP是spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。AOP可以分为静态织入与动态织入,静态织入即在编译前将需织入内容写入目标模块中,这样成本非常高。动态织入则不需要改变目标模块。Spring框架实现了AOP,使用注解配置完成AOP比使用XML配置要更加方便与直观。
AOP体系结构如下:

层次1底层编织实现模块:主要是将面向方面系统抽象封装的AOP模型编织进待增强的目标对象的实现技术。
层次2面向方面系统:配置模型,逻辑配置和AOP模型是为上策的语言和开发环境提供支持的,主要功能是将需要增强的目标对象、切面和配置使用AOP的API转换、抽象、封装成面向方面中的逻辑模型。
层次3语言和开发环境:基础是指待增加对象或者目标对象;切面通常包括对于基础的增加应用;配置是指AOP体系中提供的配置环境或者编织配置,通过该配置AOP将基础和切面结合起来,从而完成切面对目标对象的编织实现。


二、AOP的基本术语解释
1、横切关注点
 对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点。
2、切面(aspect)
类是对物体特征的抽象,切面就是对横切关注点的抽象。
3、连接点(joinpoint)
被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。
4、切入点(pointcut)
对连接点进行拦截的定义
5、通知(advice)
所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类。
6、目标对象
代理的目标对象
7、织入(weave)
将切面应用到目标对象并导致代理对象创建的过程
8、引入(introduction)
在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段


三、Spring AOP简介
AspectJ是Java 社区里最完整最流行的 AOP 框架。而在 Spring2.0 以上版本中, 可以使用基于 AspectJ 注解或基于 XML 配置的 AOP。
Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它bean实例作为目标,这种关系可由IOC容器的依赖注入提供。Spring创建代理的规则为:
1、默认使用Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了。
2、当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB。
AOP编程其实是很简单的事情,纵观AOP编程,程序员只需要参与三个部分:
1、定义普通业务组件
2、定义切入点,一个切入点可能横切多个业务组件
3、定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作
所以进行AOP编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP框架将自动生成AOP代理,即:代理对象的方法=增强处理+被代理对象的方法。


四、AOP通知类型介绍
1、Before:在目标方法被调用之前做增强处理(前置通知)
2、AfterReturning:在目标方法正常完成后做增强(后置通知)
3、AfterThrowing:主要用来处理程序中未处理的异常(异常通知)
4、After:在目标方法完成之后做增强,无论目标方法是否成功完成(最终通知)
5、Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint(环绕通知)

 


五、Spring AOP配置的两种方式
1、基于注解的方式
(1)准备
要在Spring应用中使用AspectJ注解,必须在classpath下包含AspectJ类库: aopalliance.jar、aspectj.weaver.jar 和 spring-aspects.jar。同时要在 Spring IOC 容器中启用 AspectJ 注解支持, 只要在 Bean 配置文件中定义一个空的 XML 元素 <aop:aspectj-autoproxy />即可。
这样当 Spring IOC 容器侦测到Bean配置文件中的 <aop:aspectj-autoproxy/> 元素时, 会自动为与 AspectJ切面匹配的Bean创建代理。
(2)注解声明的使用
要在Spring中声明AspectJ切面,只需要在 IOC 容器中将切面声明为Bean实例。当在 Spring IOC 容器中初始化AspectJ切面之后, Spring IOC 容器就会为那些与 AspectJ 切面相匹配的 Bean 创建代理。
在 AspectJ 注解中, 切面只是一个带有 @Aspect 注解的Java类。
AspectJ 支持 5 种类型的通知注解: 
@Before: 前置通知, 在方法执行之前执行
@After: 后置通知, 在方法执行之后执行 
@AfterRunning: 返回通知, 在方法返回结果之后执行
@AfterThrowing: 异常通知, 在方法抛出异常之后
@Around: 环绕通知, 围绕着方法执行

/** 
* @author 作者 Your-Name: 
* @version 创建时间:2019年5月31日 上午10:37:25 
* 类说明 
*/ 
package com.sumeng.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;
 
/**
 * @author Administrator
 *
 */
//将切面类交给Spring管理
@Aspect
public class UserInfoAop {
	
	//前置通知
	@Before(value="execution (* com.sumeng.aop.UserInfo.add(..))")
	public void check(JoinPoint point){
		System.out.println("添加数据之前执行的方法!!!!"+point);
	}
	//后置通知
	@AfterReturning(value="execution (* com.sumeng.aop.UserInfo.de*(..))",returning="log")
	public void checkDelect(Object log){
		System.out.println("保存日志信息之后执行!!!"+log);
	}
	//环绕通知
	@Around(value="execution (* com.sumeng.aop.UserInfo.up*(..))")
	public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
		System.out.println("环绕通知之前执行的方法!!!!");
		Object obj = joinPoint.proceed();
		System.out.println("环绕通知之后执行的方法!!!!");
		return obj;
	}
	//异常通知
	@AfterThrowing(value="execution (* com.sumeng.aop.UserInfo.che*(..))",throwing="ex")
	public void checkQuery(JoinPoint ex){
		System.out.println("异常错误"+ ex);
	}
	//始终通知
	@After(value="UserInfoAop.pointcut()")
	public void after(){
		System.out.println("始终通知!!!!");
	}
	
	
	//切入点 简化注入    相当于给@给了个 id
	@Pointcut(value="execution (* com.sumeng.aop.UserInfo.c*(..))")
	public void pointcut(){}
 
}

2、基于XML的方式
(1)准备
当使用 XML 声明切面时, 需要在 <beans> 根元素中导入 aop Schema。
在 Bean 配置文件中, 所有的 Spring AOP 配置都必须定义在 <aop:config> 元素内部. 对于每个切面而言, 都要创建一个 <aop:aspect> 元素来为具体的切面实现引用后端 Bean 实例。
切面 Bean 必须有一个标示符, 供 <aop:aspect> 元素引用。
(2)XML配置方式
切入点使用 <aop:pointcut> ,必须定义在 <aop:aspect> 元素下, 或者直接定义在 <aop:config> 元素下。若定义在 <aop:aspect> 元素下: 只对当前切面有效;若定义在 <aop:config> 元素下: 对所有切面都有效。基于 XML 的 AOP 配置不允许在切入点表达式中用名称引用其他切入点。
在 aop Schema 中, 每种通知类型都对应一个特定的 XML 元素。 通知元素需要使用 <pointcut-ref> 来引用切入点, 或用 <pointcut> 直接嵌入切入点表达式,method 属性指定切面类中通知方法的名称。
 

<?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-3.0.xsd
         http://www.springframework.org/schema/context 
         http://www.springframework.org/schema/context/spring-context-4.0.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
         <!-- 
         	init-method="getstart" 该类初始化执行的方法
         	destroy-method="getdestroy"  该类被销毁时执行的方法
         	scope="singleton" 默认为单列模式 可以  不写
         	scope="prototype" 多列模式
         	<property name="该类的属性名" value="给该类属性名注入的值"></property>
         	<import resource="user.xml"/> 若有多个配置文件可以用 inport 
          -->
     <!--  <bean id="car" class="com.sumeng.web.Car" init-method="getstart" destroy-method="getdestroy" scope="">
     	<property name="carName" value="奥迪"></property>
     </bean>  
     <import resource="user.xml"/>-->
     <!--  通过 注解 注入  类扫描器 -->
     <!--  <context:component-scan base-package="com.sumeng.web"></context:component-scan>-->
     <bean id="userInfo" class="com.sumeng.aop.UserInfo" ></bean> 
     <bean id="userInfoAop" class="com.sumeng.aop.UserInfoAop" ></bean> 
     <!-- 开启注解 -->
     <context:annotation-config />
     <!-- Aop配置 -->
     <aop:config>
     <!-- 配置切入点pointcut -->
     	<aop:pointcut expression="execution(* com.sumeng.aop.UserInfo.add(..))" id="userInfoPointcut"/>
     	<aop:pointcut expression="execution(* com.sumeng.aop.UserInfo.delete(..))" id="deletePointcut"/>
     	<aop:pointcut expression="execution(* com.sumeng.aop.UserInfo.update(..))" id="updatePointcut"/>
     	<aop:pointcut expression="execution(* com.sumeng.aop.UserInfo.check(..))" id="checkPointcut"/>
     	<!-- 配置切面 -->
     	<aop:aspect ref="userInfoAop">
     		<!-- 前置通知 -->
     		<aop:before method="check" pointcut-ref="userInfoPointcut"/>
     		<!-- 后置通知 -->
     		<aop:after-returning method="checkDelect" pointcut-ref="deletePointcut" returning="log"/>
     		<!-- 环绕通知 -->
     		<aop:around method="around" pointcut-ref="updatePointcut"/>
     		<!-- 异常通知 -->
     		<aop:after-throwing method="checkQuery" pointcut-ref="checkPointcut" throwing="ex"/>
     		<!-- 始终通知 -->
     		<aop:after method="checkQuery" pointcut-ref="checkPointcut"/>
     	</aop:aspect>
     </aop:config>
     
</beans>

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值