Spring框架实现AOP的两种实现方式

Spring AOP

概念
  1. 面向切面编程,扩展功能不需修改源代码
  2. AOP采用横向抽取机制,取代了纵向抽取机制
  3. 在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想
AOP和OOP的关系
  1. AOP面向切面编程,而OOP面向对象编程
  2. AOP是对OOP的一种补充,而不是对立关系
AOP的演变

从纵向抽取机制–>横向抽取机制

AOP底层使用动态代理方式实现

第一种情况:有接口,使用JDK动态代理方式创建接口实现类的代理对象
第二种情况:没有接口,使用cglib创建类的子类代理对象

总结
  1. 函数本身只需要实现业务逻辑即可
  2. 散落在各个功能方法上却和业务逻辑无关的功能可以封装起来,形成一个横切关注点(横切面)
AOP术语
  1. 连接点:类中可以被增强的方法,这些方法称为连接点
  2. 切入点:实际增强的方法称为切入点
  3. Advice(通知/增强):增强的逻辑称为增强,比如扩展日志功能,日志功能的逻辑就称为增强
分类含义
前置通知在方法之前执行
后置通知在方法之后执行
异常通知方法出现异常
最终通知在后置之后执行
环绕通知在方法之前和之后执行
  1. 切面:把具体增强的逻辑应用到具体执行的方法上面的过程,称为切面
    把增强用到切入点的过程
Spring实现AOP的操作

在Spring中进行aop操作,需要依赖aspectJ实现

基于aspectJ实现aop通过xml配置方式

一. 步骤

  1. 导入aop相关的jar
  2. 创建核心配置文件,导入AOP约束
  3. 准备增强类和被增强类(指定切入点和通知)
  4. 使用表达式配置切入点

二. 常用的表达式(使用表达式目的是配置切入点,完成方法的增强)
execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>),

  1. 访问修饰符:可以是public或者private 通常情况可以指定*,代表是任意的访问修饰符
  2. 方法的全路径:是增强方法的全路径,表示对这个路径下的类中的方法做增强,可以在类的后面加上*,表示对所有方法做增强
    eg:execution(* com.hpe.aop.Book.* (…))
    也可以匹配以XX开头的方法做增强execution(* save* (…)):以save开头的方法都能做增强

三. 使用xml配置切面,实现前置通知
Book.java

// 被增强类
public class Book {
	
	// 切入点
	public void add(){
		System.out.println("add...");
	}
	
	// 连接点(也是切入点)
	public void delete(){
		System.out.println("delete...");
	}
}

MyAdvice.java

// 增强类
public class MyAdvice {

	// 前置通知
	public void doBefore(){
		System.out.println("前置增强...");
	}
	
	// 后置通知
	public void doAfter(){
		System.out.println("后置增强...");
	}
	
	// 环绕通知 ProceedingJoinPoint:用来调用被增强的方法
	public void doAround(ProceedingJoinPoint p) throws Throwable{
		// 方法之前
		System.out.println("方法之前...");
		// 执行被增强的方法
		p.proceed();
		// 方法之后
		System.out.println("方法之后...");
	}
}

applicationContext.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.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
	<!-- 1.配置对象(被增强类和增强类) -->	
	<bean id="book" class="com.hpe.aop.Book"></bean>
	<bean id="myAdvice" class="com.hpe.aop.MyAdvice"></bean>
	<!-- 2.配置aop操作 -->
	<aop:config>
		<!-- 2.1配置切入点(指定对哪些方法做增强) -->
		<aop:pointcut expression="execution(* com.hpe.aop.Book.add(..))" id="pointcut1"/>
		<aop:pointcut expression="execution(* com.hpe.aop.Book.delete(..))" id="pointcut2"/>
		<!-- 2.2配置切面(把增强应用到具体的切入点) ref:增强的对象-->
		<aop:aspect ref="myAdvice">
			<!-- 增强的类型 method:增强使用哪个方法作为前置通知 pointcut-ref:把增强应用到哪个切入点上面 -->
			<aop:before method="doBefore" pointcut-ref="pointcut1"/>
			<!-- 后置通知 -->
			<aop:after-returning method="doAfter" pointcut-ref="pointcut1"/>
			<!-- 环绕通知 -->
			<aop:around method="doAround" pointcut-ref="pointcut2"/>
		</aop:aspect>
	</aop:config>	
</beans>

测试类

// 使用XML配置方式实现前置、后置通知做方法增强
@Test
public void test2(){
	// 1.读取配置文件
	ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
	// 2.获得对象
	Book book = (Book) context.getBean("book");
	// 3.访问方法
	book.add();
}

// 使用XML配置方式实现环绕通知做方法增强
@Test
public void test3(){
	// 1.读取配置文件
	ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
	// 2.获得对象
	Book book = (Book) context.getBean("book");
	// 3.访问方法
	book.delete();
}
基于aspectJ实现aop通过注解方式
AOP相关的注解
注解含义
@Aspect注解在类上面,声明一个切面
@Pointcut注解在方法上面,声明一个切入点,况且要指定aspect表达式
@Before前置通知
@After@AfterReturning后置通知,@AfterThrow异常通知
@Round环绕通知
代码实例

被增强类Person.java

// 被增强类(被代理对象)
@Component(value="person")
public class Person {
	
	public void eat(){
		System.out.println("eat...");
	}
	
	public void drink(){
		System.out.println("drink...");
	}
}

增强类MyAspect.java

// 增强类
// 3.在增强类上使用注解
@Component
@Aspect
public class MyAspect {
	
	// 在方法上面使用注解来配置通知
	// Before:前置通知;value:切入点(表达式)
	@Before(value="execution(* com.hpe.aop.Person.eat(..))")
	public void doBefore(){
		System.out.println("前置增强...");
	}
	
	@After(value="execution(* com.hpe.aop.Person.drink(..))")
	public void doAfter(){
		System.out.println("后置增强...");
	}
	
}

applicationContext2.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.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

	<!-- 1.创建对象 -->	
	<!-- <bean id="person" class="com.hpe.aop.Person"></bean>
	<bean id="myAspect" class="com.hpe.aop.MyAspect"></bean> -->
	<!-- 开启注解扫描 -->
	<context:component-scan base-package="com.hpe.aop"></context:component-scan>
	<!-- 2.使用注解的方式开启AOP的操作:开启注解扫描 -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

Test.java

// 使用注解方式实现环绕通知做方法增强
@Test
public void test4(){
	// 1.读取配置文件
	ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext2.xml");
	// 2.获得对象
	Person person = (Person) context.getBean("person");
	// 3.访问方法
	person.eat();
	person.drink();
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值