AOP面向切面编程(个人笔记1.1)

AOP面向切面编程

  • AOP面向切面编程
    • 存在的实现方式
    • 经典的基于代理的AOP:
    • AspectJ

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包:

AOP面向切面编程(个人笔记1.1)_第1张图片

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名称空间


<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/>

在通知类中进行织入的配置:

  1. 类上加@Aspect注解:

  2. 在类中指定切入点@Pointcut(“execution(…)”),标在一个空方法上面

  3. 指定各种通知方法,即在各个方法上标注@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配置文件中用 语句把通知类所在包的路径填进去

你可能感兴趣的:(#,JAVA,后端,spring,java,mybatis)