AOP面向切面编程(个人笔记1.1)
Posted 霏ིྀ宇ིྀ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AOP面向切面编程(个人笔记1.1)相关的知识,希望对你有一定的参考价值。
AOP面向切面编程
AOP面向切面编程
AOP(Aspect-Oriented Programming:面向切面编程)将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
核心概念 | 概述 |
---|---|
连接点Joinpoint | 可以进行切入开发的点。如一个方法、一个代码块、一个try块(AspectJ中原本规定可以有这些)。但是spring只支持把方法作为连接点。 |
切入点Pointcut | 已经被选定作为切面开发的点。 |
通知/增强Advice | 对切入点可以做的各种事情。如前置通知before()、后置通知after()、环绕通知around()、异常通知exception()等。 java程序中,往往把这些通知放入到一个额外的类中书写。 |
目标对象Target | (略) 目标对象是被切入的对象。但是由于类是对象的模板,是由类new()出来的,所以目标当然就是一个个的类了。 |
代理对象Proxy | (略)由于本章节,是spring自行内在完成代理对象的所有工作,我们只管用就好,所以不必专门学习。如果要知道原理请学习动态代理。 |
切面Aspect | 切入点被融入通知后,产生的整体效应。(不必强行理解这个词) |
引入(Introduction) | 引入允许我们向现有的类添加新的方法和属性(Spring提供了一个方法注入的功能) |
织入(Weaving) | 把切面应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机: (1)编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器 (2)类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码 (3)运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理应该是使用了JDK的动态代理技术 |
存在的实现方式
1.经典的基于代理的AOP
2.@AspectJ注解驱动的切面
3.纯POJO切面
4.注入式AspectJ切面
经典的基于代理的AOP:
Spring支持五种类型的通知:
Before(前) org.apringframework.aop.MethodBeforeAdvice
After-returning(返回后) org.springframework.aop.AfterReturningAdvice
After-throwing(抛出后) org.springframework.aop.ThrowsAdvice
Arround(周围) org.aopaliance.intercept.MethodInterceptor
Introduction(引入) org.springframework.aop.IntroductionInterceptor
AOP一共有两大写法,都适用于web项目
AspectJ
下载必备jar包:
java的通知都写在一个类中,其中的方法就是“通知”。可以切入到目标对象。spring支持的通知如下
1、前置通知:在目标方法之前调用
2、后置通知:(如果出现异常就不调用):在目标方法之后调用
3、后置通知:(无论是否出现异常都会调用):在目标方法之后调用
4、环绕通知:在目标方法之前、后调用
5、异常通知:出现异常时就调用
package com.qq.model;
import org.aspectj.lang.ProceedingJoinPoint;
/**
* @description:com.qq.model_studyAOP
* @author: 霏宇
* @time: 2022/7/27,15:34
*/
public class DoorAdvice
void before()
System.out.println("before()");
void after()
System.out.println("after()");
void after_returning()
System.out.println("after_returning");
void after_throwing()
System.out.println("发生异常");
void around(ProceedingJoinPoint point) throws Throwable
System.out.println("环绕通知!!!!!!");
point.proceed();
System.out.println("环绕通知2!!!!!!");
将通知织入到目标对象
先在xml文件加入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: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-4.0.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-4.0.xsd
">
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
再配置目标对象、通知对象、织入配置。共有两种写法方式(1)xml配置(2)注解配置
方法一:纯xml配置方式
<bean class="com.qq.model.Person"/>
<!-- 目标对象 -->
<bean id="doorAdvice" class="com.qq.model.DoorAdvice"/>
<aop:config>
<!-- 将通知对象织入目标对象 -->
<aop:pointcut id="enter" expression="execution(public void com.qq.model.Person.enter())"/>
<aop:aspect ref="doorAdvice"><!-- 引入通知对象--> //正因为这里的ref所以使通知对象能起作用
<aop:before method="before" pointcut-ref="enter"/>
<aop:after method="after" pointcut-ref="enter" />
<aop:after-returning method="after_returning" pointcut-ref="enter"/>
<aop:after-throwing method="after_throwing" pointcut-ref="enter"/>
<aop:around method="around" pointcut-ref="enter"/>
</aop:aspect>
</aop:config>
方法二:注解配置方式:
在xml文件中必须加上这句来开启注解:
<aop:aspectj-autoproxy/>
在通知类中进行织入的配置:
-
类上加@Aspect注解:
-
在类中指定切入点@Pointcut(“execution(…)”),标在一个空方法上面
-
指定各种通知方法,即在各个方法上标注@Before 、@After 、@Around等等,并添加
package com.qq.model; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; /** * @description:com.qq.model_studyAOP * @author: 霏宇 * @time: 2022/7/27,15:34 */ //通知类 @Aspect public class DoorAdvice @Pointcut("execution(public void com.qq.model.Person.enter())") void point() @Before("DoorAdvice.point()") void before() System.out.println("before()"); @After("DoorAdvice.point()") void after() System.out.println("after()"); @AfterReturning("DoorAdvice.point()") void after_returning() System.out.println("after_returning"); @AfterThrowing("DoorAdvice.point()") void after_throwing() System.out.println("发生异常"); @Around("DoorAdvice.point()") Object around(ProceedingJoinPoint point) throws Throwable System.out.println("环绕通知!!!!!!"); Object proceed = point.proceed(); System.out.println("环绕通知2!!!!!!"); return proceed;
另外
通知类也是一个,如果我们不想在xml中书写,也可以改成用注解的方式,即需要做
1、 使用@component标注通知类
2、在xml配置文件中用<context:component-scan base-package=“通知类包路径” /> 语句把通知类所在包的路径填进去
以上是关于AOP面向切面编程(个人笔记1.1)的主要内容,如果未能解决你的问题,请参考以下文章