Spring:AOP(XML配置)

本文详细介绍了Spring中的AOP(面向切面编程)概念,包括AOP的原理、操作术语以及基于AspectJ的XML配置。通过具体例子展示了如何定义连接点、切入点、通知类型,并给出了切入点表达式的示例,以及配置文件的编写方式。
摘要由CSDN通过智能技术生成

AOP

AOP:面向切面编程,扩展功能不修改源代码实现。

AOP原理

AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码

纵向抽取机制

当我们有一个添加数据的方法add,此时需求在add方法执行后添加日志功能记录。

方法一:如左图,在add方法中直接添加日志逻辑,此时需要修改源代码。

方法二:如右图,为了不修改源代码,我们单独写一个添加日志的方法writelog,将writelog所在类当作父类,每个需要添加日志的类都继承此类,只需要在add方法最后调用父类的writelog方法,此时优化了方法一的代码,可是还不够好,当父类方法名改变时,子类调用时也需要改,这样又得修改源代码。这种调用父类方法添加功能叫纵向抽取机制,却仍然达不到我们的目的,所以接下来我们使用另一种机制解决。

横向抽取机制

 

横向抽取机制底层分两种情况实现。

情况一:如左图,当Dao是接口,DaoImpl是接口实现类,即有接口时,采用jdk动态代理创建DaoImpl类(接口实现类)的代理对象,实现功能。

情况二:如右图,只有User一个类,即没有接口时,采用cglib动态代理创建User类子类(父类的子类)的代理对象,通过调用父类方法完成增强。

AOP操作术语

Joinpoint(连接点):类里面可以被增强的方法,这些方法称为连接点。

Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义。

Advice(通知/增强):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知,通知分为前置通知、后置通知、异常通知、最终通知、环绕通知(切面要完成的功能)。

Aspect(切面):是切入点和通知(引介)的结合。

Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下,Introduction可以在运行期为类动态地添加一些方法或Field。

Target(目标对象):代理的目标对象(要增强的类)。

Weaving(织入):是把增强应用到目标的过程,把Advice 应用到 Target的过程。

Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类。

 

基于aspectj的XML配置AOP

在Spring里面进行AOP操作,使用aspectj实现。aspectj不是Spring一部分,和Spring一起使用进行aop操作,Spring2.0以后新增了对AspectJ支持。

Aop操作准备

1、除了导入基本的jar包之外,还需要导入aop相关的jar包

 

2、创建Spring核心配置文件,导入AOP的约束

<?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.xsd">
        
</beans>

切入点表达式

execution ( [方法访问修饰符] 方法返回值 包名.类名.方法名(方法参数) [异常] )

方法返回值:可以用*表示任何返回值,全路径的类名等。

方法名:*代表所有,set*代表以set开头的所有方法。

方法参数:指定方法参数(声明的类型),(..)代表所有参数,(*)代表一个参数,(*,String)代表第一个参数为任何值,第二个为String类型。

public * cn.itcast.spring.dao.*.*(..)        public修饰的dao包下所有类的所有方法

* cn.itcast.spring.dao.*.*(..)                  dao包下所有类的所有方法

* cn.itcast.spring.dao.UserDao+.*(..)   dao包下UserDao接口及接口实现类的所有方法

* cn.itcast.spring.dao..*.*(..)                 dao包下,子孙包下所有方法

* save*(..)                                             所有save开头的方法

通知的类型

前置通知 <aop:before>:在目标方法执行之前执行

后置通知 <aop:after-returning>:在目标方法执行之后执行

环绕通知 <aop:around>:在目标方法执行前和执行后执行,使用proceedingJoinPoint.proceed();调用目标方法

异常抛出通知<aop:after-throwing>:在目标方法执行出现异常的时候执行

最终通知 <aop:after>:无论目标方法是否出现异常最终通知都会执行

Aop实例

Book类

public class Book {

	public void bookp() {
		System.out.println("bookp方法运行");
	}
}

Order类

public class order() {
    
   public void before() {
		System.out.println("before方法运行");
	}

	public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
		System.out.println("bookp方法运行之前");
		proceedingJoinPoint.proceed();// 使用point.proceed()调用被增强的方法,抛出异常
		System.out.println("bookp方法运行之后");
	}

	public void after_returning() {
		System.out.println("after_returning方法运行");
	}

	public void after_throwing() {
		System.out.println("after-throwing方法运行");
	}

	public void after() {
		System.out.println("after方法运行");
	}
 }

配置文件

<?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.xsd">

	<bean id="book" class="org.haiwen.pojo.Book"></bean>
	<bean id="order" class="org.haiwen.pojo.Order"></bean>

	<aop:config>
		<!-- 配置切入点 -->
		<aop:pointcut expression="execution(* org.haiwen.pojo.Book.bookp(..))" id="pointcut"></aop:pointcut>
		
		<!-- 配置切入面 -->
		<aop:aspect ref="order">
		
			<!-- pointcut-ref与切入点的id匹配 -->
			<!-- <aop:before method="before" pointcut-ref="pointcut" /> -->
			<!-- <aop:around method="around" pointcut-ref="pointcut" /> -->
			<!-- <aop:after-returning method="after_returning" pointcut-ref="pointcut" /> -->
			<!-- <aop:after-throwing method="after_throwing" pointcut-ref="pointcut" /> -->
			<!-- <aop:after method="after" pointcut-ref="pointcut" /> -->
		</aop:aspect>
	</aop:config>
</beans>

运行结果

before

before方法运行

bookp方法运行

around

bookp方法运行之前

bookp方法运行

bookp方法运行之后

after_returning

bookp方法运行

after_returning方法运行

after_throwing

bookp方法运行

after

bookp方法运行

after方法运行

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值