实习笔记 —— AOP开发I

本文详细介绍了Spring的面向切面编程(AOP)概念,包括AOP的基本术语,如连接点、切入点、通知等,并通过实例展示了如何在Spring中配置和使用AOP进行功能增强。通过购物平台的例子,对比了AOP与OOP的差异,阐述了AOP在减少代码重复和提高开发效率上的优势。此外,还提供了完整的AOP代码示例,包括接口、实现类、切面类的编写以及XML配置,最后进行了总结,梳理了AOP编程的完整流程。
摘要由CSDN通过智能技术生成

系列文章目录

实习笔记 —— Spring基础
实习笔记 —— IOC反转控制(xml配置文件 + 注解)



一、什么是AOP?

1.简介

AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

简单来说,AOP就是通过运行期间生成动态代理的方式,实现代码隔离,维护方便,功能增强效果。

2.与OOP的对比

AOP是面向切面编程,横向
OOP是面向对象编程,纵向

AOP原理,以开发网络购物平台为例:
在这里插入图片描述

此为纵向开发的例子,包括5个模块。
购物车的商品不写数据库,因为购物车的商品变更比较频繁,引发数据库抖动。

若在上述模块都完成后又需增加两项功能:显示用户等级、徽章等身份 + 在每次跳转页面时验证用户身份。按照传统做法(没有切面编程),我们得一项一项地添加到每个模块中,对代码进行整理和增删,效率很低。
在切面编程中,将新添加的两个功能单独写在一个模块中,使用spring的注入方式将其注入到需要这些功能的模块中,原有的模块完全不需改变。既提高了开发效率,又维持了原有代码的稳定。
在这里插入图片描述

3.AOP的相关术语

①Joinpoint:连接点,待增强或完善的那些已写好的模块/方法(我们主要针对方法)

②Pointcut:切入点,真正需要做的连接点(连接点是众多候选人,切入点是得奖者,可能不止一个)

③Advice:通知,增强;甲方要求新增加的方法或需求(如上述显示用户身份需求)

④Target:目标,切入点(被增强的方法)所属的类

⑤Weaving:织入,将Advice应用到Target的过程(将甲方新增的需求应用到某个切入点的过程,即颁奖仪式)

⑥Aspect:切面,多个Weaving过程配置(单个Weaving是点对点的,多个累计就形成了面),构成切面

请添加图片描述

二、AOP代码简例

创建了新的项目结构:
在这里插入图片描述
com.high.demo1包的内容:
在这里插入图片描述
①创建接口:
在这里插入图片描述
②接口的实现类:
在这里插入图片描述
③切面类:
在这里插入图片描述
④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: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>

配置文件内容:

<?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">
        
	
	<!-- 把ProductDaoImpl类交给spring管理 -->
	<!-- 创建目标类 target -->
 	<bean name="productDao" class="com.high.demo1.ProductDaoImpl"></bean>      
 	       
   	<!-- 将切面类交给spring管理 -->
   	<bean name="myAspect" class="com.high.demo1.MyAspectXML"></bean>  
   	 
   	<!-- 通过AOP配置来完成对目标的代理 -->
   	<!-- MyAspectXML类中的checkPri作用于切入点pointcut1上 -->
   	<aop:config>
   		<!-- 声明第一个切入点,id值全局唯一 -->	
   		<aop:pointcut id="pointcut1" expression="execution(* com.high.demo1.ProductDaoImpl.save(..))"/>
   		<aop:pointcut id="pointcut2" expression="execution(* com.high.demo1.ProductDaoImpl.delete(..))"/>
   		
   		
   		
   		<!-- 引入切面类MyAspect  -->
   		<aop:aspect ref="myAspect">
   			<!-- 完成织入过程,切面类作用在谁身上(只写方法名),以及切入点 -->
   			<!-- 通知的类型:1.前置通知 before -->
   			<aop:before method="checkPri" pointcut-ref="pointcut1"/>
   			<!-- 2.后置通知 after-returning -->
   			<aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"/>
   			
   		</aop:aspect>
   	</aop:config>
</beans>

⑤测试类:

package com.high.demo1;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

// AOP入门 
// 书写类注解,类层级,所以写在类外面
// 整合JUnit4
@RunWith(SpringJUnit4ClassRunner.class)
// 加载XML配置文件(严格按照格式书写,不要添加任何空格等字符)
@ContextConfiguration("classpath:applicationContext.xml")

public class SpringDemo {
	
	// 1.未使用注解整合JUnit
//	@Test
//	public void demo() {
//		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//		ProductDaoImpl product = (ProductDaoImpl)applicationContext.getBean("productDao");
//		
//		product.save();
//		product.update();
//		product.delete();
//		product.find();
//	}
	
	// 2.整合后
	// 想用哪个类就注入哪个类,交给spring管理
	
	// 对私有属性的引入
	@Resource(name = "productDao")
	private ProductDao productDao;
		
	@Test
	public void demo2() {
		productDao.save();
		productDao.update();
		productDao.delete();
		productDao.find();
	}
}

测试结果:
在这里插入图片描述

三、今日总结

1.切入点 + Advice 是今天内容的重点。
2.修改的内容都在文件/spring03/src/com/high/demo1/MyAspectXML.java + /spring03/src/applicationContext.xml 中。测试类、接口、接口的实现类都无需改变。
3.总结一下AOP编程的流程:
①创建接口,接口中有若干待方法。
②创建接口的实现类,此时实现类中实现的是基本功能,若甲方提出新的需求,就轮到AOP编程出场了。
③编写XML配置文件,将接口的实现类交给spring管理。

 	<bean name="productDao" class="com.high.demo1.ProductDaoImpl"></bean>      

(完成这步后可在测试类中加载配置文件并获取实现类对象,执行实现类中实现的接口的方法以判断到此为止的初步书写是否正确)

@Test
public void demo() {
	ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
	ProductDaoImpl product = (ProductDaoImpl)applicationContext.getBean("productDao");
		
	product.save();
	product.update();
	product.delete();
	product.find();
}

④若此时甲方新的需求到来了,则需要编写切面类,存放甲方要增加的方法,举两例:

public class MyAspectXML {
	// 前置通知
	public void checkPri(JoinPoint jointJoinpoint) {
		System.out.println("save方法的前置通知:进行身份验证........" + jointJoinpoint);
	}
	
	// 后置通知
	public void writeLog(Object result) {
		System.out.println("delete方法的后置通知:Be recorded....." + result);
	}
}

要实现在save方法执行前增加新的输出语句,并在delete方法执行后增加新的输出语句。

编写好切面类,需编写XML配置文件,将切面类交给spring管理:

<bean name="myAspect" class="com.high.demo1.MyAspectXML"></bean>  

后续操作:声明切入点,将通知(Advice)应用到切面类(Target),即进行织入过程:

<!-- 通过AOP配置来完成对目标的代理 -->
<!-- MyAspectXML类中的checkPri作用于切入点pointcut1上 -->
<aop:config>
   	<!-- 声明第一个切入点,id值全局唯一 -->	
   	<aop:pointcut id="pointcut1" expression="execution(* com.high.demo1.ProductDaoImpl.save(..))"/>
   	<aop:pointcut id="pointcut2" expression="execution(* com.high.demo1.ProductDaoImpl.delete(..))"/>
   		
   		
   		
   	<!-- 引入切面类MyAspect  -->
   	<aop:aspect ref="myAspect">
   		<!-- 完成织入过程,切面类作用在谁身上(只写方法名),以及切入点 -->
   		<!-- 通知的类型:1.前置通知 before -->
   		<aop:before method="checkPri" pointcut-ref="pointcut1"/>
   		<!-- 2.后置通知 after-returning -->
   		<aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"/>
   			
   	</aop:aspect>
</aop:config>

⑤之后只需编写测试类,获取接口实现类的对象后调用其中的方法,看看我们是否将在原有方法基础上实现了新需求:

// 2.整合后
// 想用哪个类就注入哪个类,交给spring管理
	
// 对私有属性的引入
@Resource(name = "productDao")
private ProductDao productDao;
		
@Test
public void demo2() {
	productDao.save();
	productDao.update();
	productDao.delete();
	productDao.find();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring AOPSpring框架中的一个重要模块,它提供了面向切面编程(AOP)的支持。AOP是一种编程思想,它可以在不改变原有代码的情况下,通过在程序运行时动态地将代码“织入”到现有代码中,从而实现对原有代码的增强。 Spring AOP提供了基于注解的AOP实现,使得开发者可以通过注解的方式来定义切面、切点和通知等相关内容,从而简化了AOP的使用。 下面是一个基于注解的AOP实现的例子: 1. 定义切面类 ```java @Aspect @Component public class LogAspect { @Pointcut("@annotation(Log)") public void logPointcut() {} @Before("logPointcut()") public void beforeLog(JoinPoint joinPoint) { // 前置通知 System.out.println("执行方法:" + joinPoint.getSignature().getName()); } @AfterReturning("logPointcut()") public void afterLog(JoinPoint joinPoint) { // 后置通知 System.out.println("方法执行完成:" + joinPoint.getSignature().getName()); } @AfterThrowing(pointcut = "logPointcut()", throwing = "ex") public void afterThrowingLog(JoinPoint joinPoint, Exception ex) { // 异常通知 System.out.println("方法执行异常:" + joinPoint.getSignature().getName() + ",异常信息:" + ex.getMessage()); } } ``` 2. 定义业务逻辑类 ```java @Service public class UserService { @Log public void addUser(User user) { // 添加用户 System.out.println("添加用户:" + user.getName()); } @Log public void deleteUser(String userId) { // 删除用户 System.out.println("删除用户:" + userId); throw new RuntimeException("删除用户异常"); } } ``` 3. 在配置文件中开启AOP ```xml <aop:aspectj-autoproxy/> <context:component-scan base-package="com.example"/> ``` 在这个例子中,我们定义了一个切面类LogAspect,其中通过@Aspect注解定义了一个切面,通过@Pointcut注解定义了一个切点,通过@Before、@AfterReturning和@AfterThrowing注解分别定义了前置通知、后置通知和异常通知。 在业务逻辑类中,我们通过@Log注解标注了需要增强的方法。 最后,在配置文件中,我们通过<aop:aspectj-autoproxy/>开启了AOP功能,并通过<context:component-scan>扫描了指定包下的所有组件。 这样,当我们调用UserService中的方法时,就会触发LogAspect中定义的通知,从而实现对原有代码的增强。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值