Spring 学习笔记 -AOP 入门

本贴最后更新于 2210 天前,其中的信息可能已经事过景迁

AOP 的概述

什么是 AOP

在软件业,AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。==AOP 是 OOP 的延续==,是软件开发中的一个热点,也是 Spring 框架中的一个重要内容,是函数式编程的一种衍生范型。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。——————百度百科

Spring 底层的 AOP 实现原理

动态代理
- JDK 动态代理:只能对实现了接口的类产生代理
- Cglib 动态代理:对没有实现接口的类产生代理。生产子类对象

++ 动态代理相关详细请看《java 代理模式的那些事》++

Spring 的 AOP 的开发

Spring 的 AOP 的简介

AOP 思想最早由 AOP 联盟组织提出的,Spring 是使用这种思想最好的框架。前期,Spring 的 AOP 也有自己的实现方式,但是非常繁琐。不过当时有一款非常好的 AOP 框架-AspectJ,Spring 便引入 AspectJ 作为自身的 AOP。so,Spring 有两套 AOP 开发方式:Spring 传统方式、Spring 基于 AspectJ 的方式。

AOP 开发中的术语

  • Joinpoint:连接点,可以被拦截到的点(方法、类)。
  • Pointcut:切入点,真正被拦截到的点(方法、类)。
  • Advice:通知(或者叫增强),对切入点进行权限校验等动作的方法称为通知(方法层面的增强)。
  • Introduction:引介,类层面的增强
  • Target:被增强的对象
  • Weaving:织入,将通知(Advice)应用到目标(Target)过程。
  • proxy:代理对象
  • Aspect:切面,多个通知和多个切入点组合
Class UserDao{
	public void save();
    public void find();
    public void update();
    public void delete();
}
/**
*	save、find、update、delete方法都可以被称为连接点
*	如果在实际开发中,只对save方法进行增强,则save被称为切入点
*	如果现在要对save方法进行权限校验(checkPri();),则权限校验(checkPri();)的方法则称为通知
*	Target是指被增强的对象,也就是UserDao
*/

进入 AspectJ 的 XML 方式开发

创建 web 项目,引入 jar 包

  1. 引入 Spring 的 6 个基本 jar 包(commons-logging、log4j、beans、context、core、expression)
  2. 引入 AOP 开发的相关 jar 包(aop、aspects)
  3. 引入 aop 的 XML 约束
<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>

编写目标类并完成配置

public class ProductDaoImpl implements ProductDao{
	public void save(){
    	//TODO
    }
    public void update(){
    	//TODO
    }
    public void find(){
    	//TODO
    }
    public void delete(){
    	//TODO
    }
}
<!-- 配置目标对象:被增强的对象 -->
<bean id="productDao" class="com.spring.demo.ProductDaoImpl" />

编写测试类

@RunWith(SpringJunit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo{
    @Resource(name="productDao")
    private ProductDao productDao;
    
    @Test
    public void demo1(){
    	productDao.save();
    	productDao.update();
    	productDao.find();
    	productDao.delete();
    }
}

编写切面类

//切面类
public class MyAspectXML{
	
    public void checkPri(){
    	System.out.println("权限校验。。。。。。。。");
    }
}
<!-- 将切面类交给Spring管理 -->
<bean id="myAspect" class="com.spring.demo.MyAspectXML" />

通过 AOP 的配置来实现目标代理

<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="productDao" class="com.spring.demo.ProductDaoImpl" />
    <!-- 将切面类交给Spring管理 -->
    <bean id="myAspect" class="com.spring.demo.MyAspectXML" />
    
    <!-- 通过AOP的配置完成对目标类产生代理 -->
    <aop:config>
    	<!-- experssion:通过表达式配置哪些类的哪些方法需要进行增强 -->
    	<aop:pointcut experssion="execution(* com.spring.demo.ProductDaoImpl.save(..))" id="pointcut1"/>
        
        <!-- 配置切面 -->
        <aop:aspect ref="myAspect">
        	<aop:before method="checkPri" pointcut-ref="pointcut1"/>
        </aop:aspect>
    </aop:config>
</beans>

Spring 中的通知类型

前置通知:在目标方法执行之前进行操作

获得切入点信息

<aop:aspect ref="myAspect">
        	<aop:before method="checkPri" pointcut-ref="pointcut1"/>
</aop:aspect>

后置通知:在目标方法执行之后进行操作

获得方法的返回值

<aop:aspect ref="myAspect">
        	<aop:after-returning method="checkPri" pointcut-ref="pointcut1" returning="result"/>
</aop:aspect>

环绕通知:在目标方法执行前后进行操作

环绕通知可以阻止目标方法的执行(ProceedingJoinPoint.proceed() 执行切入点)

<aop:aspect ref="myAspect">
        	<aop:around method="checkPri" pointcut-ref="pointcut1"/>
</aop:aspect>

异常抛出通知:在程序出现异常的时候,进行的操作

<aop:aspect ref="myAspect">
        	<aop:after-throwing method="checkPri" pointcut-ref="pointcut1" throwing="ex"/>

最终通知:无论代码时候有异常,总是会执行。(相当于 try catch 中的 finally)

<aop:aspect ref="myAspect">
        	<aop:after method="checkPri" pointcut-ref="pointcut1"/>

Spring 的切入点表达式的写法

==基于 execution 的函数完成的==

基本语法:

  • [访问修饰符] 方法返回值 包名.类名.方法名(参数)
  • public void com.spring.demo.UserDao.save(..)
  • public 可省略。返回值可以是具体的 String void,也可以是 * 表示任意返回值。.. 表示任意参数
  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3454 回帖 • 188 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    943 引用 • 1460 回帖 • 1 关注
  • 学习

    “梦想从学习开始,事业从实践起步” —— 习近平

    171 引用 • 513 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...