柏竹 柏竹
首页
后端
前端
  • 应用推荐
关于
友链
  • 分类
  • 标签
  • 归档

柏竹

奋斗柏竹
首页
后端
前端
  • 应用推荐
关于
友链
  • 分类
  • 标签
  • 归档
  • Java基础

  • JavaWeb

  • 拓展技术

  • 框架技术

  • 数据库

  • 数据结构

  • Spring

    • Spring
    • Spring IOC
    • Spring AOP
      • AOP代理
        • 静态代理
        • 动态代理
        • 基于JDK的动态代理
        • 基于CGLIB的动态代理
      • AOP通知
        • 通知种类
        • AOP术语
        • AspectJ 实现AOP
        • 切入点表达式
        • XML实现AOP
        • 注解实现AOP
        • XML与Annotation 声明区别
    • Spring拓展
  • SpringMVC

  • SpringBoot

  • SpringClound

  • Ruoyi-Vue-Plus

  • 后端
  • Spring
柏竹
2021-07-04
目录

Spring AOP

AOP 的全称是“Aspect Oriented Programming” 面向切面编程,是一种编程模式,将业务逻辑的各个部分进行隔离,使开发业务逻辑时可 减少代码重复率、提高业务开发效率

# AOP代理

代理:自己不做,找人帮你做

代理模式:在一个原有功能的基础上添加新的功能

分类:静态代理和动态代理

# 静态代理

将 服务性代码 分离出来。通过接口进行静态代理

接口

public interface IService {
	void add();
}

业务类

public class UserService implements IService {
    @Override
    public void add() {
        System.out.println("UserService---user---");
    }
}

代理类

public class Proxy_affair implements IService {
    private IService iService;
    
    public Proxy_affair(IService iService) {
        this.iService = iService;
    }
    
    @Override
    public void add() {
        try {
            System.out.println("事务开启");
            
            //核心业务
            iService.add();
            
            System.out.println("事务结束");
        } catch (Exception e) {
            System.out.println("事务回滚");
        }
    }
}

测试类

@Test
public void test() {
    UserService userService = new UserService();
    //一级代理(事务)
    Proxy_affair proxy_affair = new Proxy_affair(userService);
    
    //二级代理(日志)
    //添加多个业务进行测试
    //Proxy_log proxy_log = new Proxy_log(proxy_affair);
    //proxy_log.add();
    
    proxy_affair.add();
}

/*运行结果

日志开始
事务开启
UserService---add---
事务结束
日志结束

*/

总结

  • 代理在不修改 业务功能 的前提下,对 业务功能 进一步进行拓展
  • 如果有 多个代理类 会影响 接口方法增加 和 维护难度

# 动态代理

程序运行的时候,根据要被代理的对象动态生成代理类

动态代理有类型两种类型分为 基于JDK的动态代理 和 基于CGLIB的动态代理

# 基于JDK的动态代理

JDK代理的前提 目标对象 必须实现接口,否则无法实现JDK动态代理

Proxy类

Class Proxy

java.lang.Object java.lang.reflect.Proxy

Proxy 提供创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类

主要方法

Proxy.newProxyInstance

public static Object newProxyInstance(ClassLoader loader,
                                      类<?>[] interfaces,
                                      InvocationHandler h)
                               throws IllegalArgumentException

ClassLoader loader: 类加载器,因为动态代理类,借助别人的类加载器。一般使用被代理对象的类加载器

Class[] interfaces: 接口类对象的集合,针对接口的代理,针对哪个接口做代理

InvocationHandler h: 句柄,回调函数,编写代理的规则代码

InvocationHandler.invoke (接口方法)

Object invoke(Object proxy,
              方法 method,
              Object[] args)
       throws Throwable

Object proxy: 代理对象

Method method: 被代理的方法

Object[] args: 被代理方法的 参数数组

原始实例 (main方法实现)

业务类

public class UserService implements IService {
    @Override
    public void add() {
        System.out.println("UserService---user---");
    }
}

main方法执行

public static void main(String[] args) {
    //目标对象
        UserService userService = new UserService();
        
        //返回代理对象
        IService proxyService = (IService) Proxy.newProxyInstance(
                //目标对象类 加载器
                userService.getClass().getClassLoader() ,
                //实现的接口集合
                userService.getClass().getInterfaces() ,
                //动态代理 规则编辑
                new InvocationHandler() {
                    /**
                     * @param proxy 代理对象
                     * @param method 被代理的方法
                     * @param args 被代理方法的 参数数组
                     * @return 被代理方法的返回
                     */
                    @Override
                    public Object invoke(Object proxy , Method method , Object[] args) throws Throwable {
                        Object invoke = null;
                        try {
                            System.out.println("开始事务");
                            
                            //核心业务
                            invoke = method.invoke(userService,args);
                            
                            System.out.println("提交事务");
                        } catch (Exception e) {
                            System.out.println("事务回滚");
                            e.printStackTrace();
                            throw e;
                        }finally {
                            System.out.println("finally---");
                        }
                        System.out.println("invoke : " + invoke);
                        return invoke;
                    }
                }
        );
        //执行代理业务
        proxyService.add();
}

/*运行结果

开始事务
UserService---add---
提交事务
finally---
invoke : null

*/

工具化设计

业务类

public class UserService implements IService {
    @Override
    public void add() {
        System.out.println("UserService---user---");
    }
}

Aop接口

/**
 * 切面:服务代码,切入核心代码
 */
public interface Aop {
    
    //4个阶段
    void before();
    void after();
    void exception();
    void myFinally();
    
}

切面类 (事务)

public class TranLAop implements Aop{
    @Override
    public void before() {
        System.out.println("事务---before");
    }
    
    @Override
    public void after() {
        System.out.println("事务---after");
    }
    
    @Override
    public void exception() {
        System.out.println("事务---exception");
    }
    
    @Override
    public void myFinally() {
        System.out.println("事务---myFinally");
    }
}

工具类

public class ProxyFactory {
    
    private IService iService;
    private Aop aop;
    
    public ProxyFactory(IService iService , Aop aop) {
        this.iService = iService;
        this.aop = aop;
    }
    
    public IService getProxyInstance(){
        return (IService) Proxy.newProxyInstance(
                //目标对象类 加载器
                iService.getClass().getClassLoader() ,
                //实现的接口集合
                iService.getClass().getInterfaces() ,
                //动态代理 规则编辑
                new InvocationHandler() {
                    /**
                     * @param proxy 代理对象
                     * @param method 被代理的方法
                     * @param args 被代理方法的参数
                     * @return 被代理方法的返回
                     */
                    @Override
                    public Object invoke(Object proxy , Method method , Object[] args) throws Throwable {
                        Object invoke = null;
                        try {
                            aop.before();
                            //核心业务
                            invoke = method.invoke(iService,args);
                            aop.after();
                        } catch (Exception e) {
                            aop.exception();
                            e.printStackTrace();
                            throw e;
                        }finally {
                            aop.myFinally();
                        }
                        return invoke;
                    }
                }
        );
    }
    
}

测试类

//工具化 实现动态代理
@Test
public void test() {
    UserService userService = new UserService();
    TranLAop tranLAop = new TranLAop();
    IService proxyFactory = new ProxyFactory(userService,tranLAop).getProxyInstance();
    proxyFactory.add();
}

/*运行结果

事务---before
UserService---add---
事务---after
事务---myFinally

*/

# 基于CGLIB的动态代理

Cglib代理,也称子类代理。在内存中构建一个子类对象从而实现对目标对象功能的扩展(目标对象无需应用接口也可实现目标对象的代理)

GLIB 被许多 AOP 框架所使用,其底层是通过使用一个小而快的字节码处理框架 ASM(Java 字节码操控框架)转换字节码并生成新的类

应用前提需要引入Cglib动态代理jar

<!--CGLIB的动态代理-->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.2</version>
</dependency>

业务类 (学生类)

public class StudentService {
    public void add(int id , String name) {
        System.out.println("StudentService---add---");
        System.out.println("引入数据: " + id +"--"+name);
    }
}

main方法执行

public static void main(String[] args) {
//目标对象(无接口)
    StudentService service = new StudentService();
    //cglib动态代理 (因 无接口,使用类型是与目标对象一直)
    StudentService proxyService = (StudentService) Enhancer.create(
            //目标对象类
            service.getClass() ,
            //回调对象代理规则
            new MethodInterceptor() {
                /**
                 *
                 * @param o
                 * @param method 针对方法
                 * @param objects
                 * @param methodProxy
                 * @return 调取方法的返回
                 */
                @Override
                public Object intercept(Object o , Method method , Object[] objects , MethodProxy methodProxy)
                        throws Throwable {
                    try {
                        System.out.println("开始事务");
                        //核心业务
                        Object invoke = methodProxy.invokeSuper(o , objects);
                        
                        System.out.println("提交事务");
                        return null;
                    } catch (Throwable throwable) {
                        System.out.println("事务回滚");
                        throw throwable;
                    } finally {
                        System.out.println("finally-----");
                    }
                }
            }
    );
    proxyService.add(001 , "张三");
}


/*运行结果

开始事务
StudentService---add---
引入数据: 1--张三
提交事务
finally-----

*/

工具化设计

业务类

public class StudentService {
    public void add(int id , String name) {
        System.out.println("StudentService---add---");
        System.out.println("引入数据: " + id +"--"+name);
    }
}

Aop接口

/**
 * 切面:服务代码,切入核心代码
 */
public interface Aop {
    
    //4个阶段
    void before();
    void after();
    void exception();
    void myFinally();
    
}

切面类 (日志)

public class LogAop implements Aop{
    
    @Override
    public void before() {
        System.out.println("日志---before");
    }
    
    @Override
    public void after() {
        System.out.println("日志---after");
    }
    
    @Override
    public void exception() {
        System.out.println("日志---exception");
    }
    
    @Override
    public void myFinally() {
        System.out.println("日志---myFinally");
    }
}

工具类

public class CglibProxyFactory {
    
    private StudentService service;
    private Aop aop;
    
    public CglibProxyFactory(StudentService service , Aop aop) {
        this.service = service;
        this.aop = aop;
    }
    
    public Object getProxyInstance() {
        return Enhancer.create(
                //目标对象类
                service.getClass() ,
                //回调对象代理规则
                new MethodInterceptor() {
                    /**
                     *
                     * @param o
                     * @param method 针对方法
                     * @param objects
                     * @param methodProxy
                     * @return 调取方法的返回
                     */
                    @Override
                    public Object intercept(Object o , Method method , Object[] objects , MethodProxy methodProxy)
                            throws Throwable {
                        try {
                            aop.before();
                            //核心业务
                            Object invoke = methodProxy.invokeSuper(o , objects);
                    
                            aop.after();
                            return null;
                        } catch (Throwable throwable) {
                            aop.exception();
                            throw throwable;
                        } finally {
                            aop.myFinally();
                        }
                    }
                }
        );
    }
    
}

测试类

@Test
public void test() {
    //目标对象(无接口)
    StudentService service = new StudentService();
    //cglib动态代理 (因 无接口,使用类型是与目标对象一直)
    Aop aop = new LogAop();
    StudentService proxyInstance = (StudentService) new CglibProxyFactory(service , aop).getProxyInstance();
    proxyInstance.add(001,"张三");
}

/*运行结果

日志---before
StudentService---add---
引入数据: 1--张三
日志---after
日志---myFinally

*/

# AOP通知

Spring的AOP实现底层就是对上面动态代理的代码进行封装,封装后我们子需要对关注部分进行代码编写,并通过配置的方式完成指定目标的方法增强

# 通知种类

Spring 通知 指定目标类方法 的连接点位置,分为以下5种通知类型

  1. 前置通知 在方法执行前的通知,可以应用于权限管理等功能
  2. 后置通知 在方法执行后的通知,可以应用于关闭流、上传文件、删除临时文件等功能
  3. 环绕通知 在方法执行 前、后 都通知,可以应用于日志、事务管理等功能
  4. 异常通知 在方法抛出异常时的通知,可以应用于处理异常记录日志等功能
  5. 最终通知 方法执行完毕后最后的通知

# AOP术语

  • Target(目标对象) 要被增强的对象,一般业务逻辑类对象
  • Proxy(代理) 一个类被AOP 织入增强后,产生一个结果代理类
  • Aspect(切面) 切面点 增强功能 , 就是一些代码完成某些功能 , 非业务功能。是切入点和通知的结合
  • Joinpoint(连接点) 程序执行过程中 明确的点。在Spring中,这些点指定与 核心业务的方法(Spring只支持方法类型的连接点)
  • Pointcut(切入点) 切入点 指 声明 一个/多个 连接点的集合。通过切入点指定一组方法(非final方法)
  • Advice(通知/增强) 通知 指 拦截到 连接点 后要做的 通知。通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是之后执行等。通知类型不同,切入时间不同
  • Weaving(织入) 织入 指 增强应用到目标对象来创建新的代理对象的过程。 spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入

# AspectJ 实现AOP

AspectJ 基于 Java语言的AOP框架,它扩展了 Java语言,使得AOP功能使用更便捷

# 切入点表达式

AspectJ 定义 专门的表达式 指定 切入点 . 通用型 execution表达式原型:

execution([modifiers-pattern] ret-type-pattern declaring-type-pattern name-pattern(param-pattern) [throws-pattern])

//必要参数:方法返回值 方法声明(参数)
execution(访问权限 方法返回值 方法声明(参数) 异常类型)

参数说明 (中括号表示可选类型)

  • modifiers-pattern :访问权限类型
  • ret-type-pattern :返回类型
  • declaring-type-pattern :包名类名
  • name-pattern(param-pattern) :方法名(参数的 类型 和 个数)
  • throws-pattern :抛出异常类型

PS : 表达式各个部分可以用空格隔开,可用以下符号

符号 范围 说明
* 所有 0 ~ n 个任意字符
.. 方法参数、包路径 指定任意个参数;当前包的子路径
+ 类名、接口 当前类路径的子类;当前接口及实现的类

切入点表达式实例

execution(* com.service.*.*(..)) 定义 com.service 包路径里的 任意类、任意方法、方法任意返回类型

execution(* com.service..*.*(..)) 定义 com.service 包路径里的 任意子包、任意类、任意方法、方法任意返回类型

execution(* com.service.IUserService+.*(..)) 当路径 com.service.IUserService 的文件类型为以下条件: 若为接口 , 则为接口中 任意方法及其所有实现类中的任意方法 若为类 , 则为该类及其子类中的任意方法

# XML实现AOP

基于 xml 的配置文件方式进行定义 切面、切入点 等

依赖、插件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.sans</groupId>
    <artifactId>Spring-AOP</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>15</maven.compiler.source>
        <maven.compiler.target>15</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <!-- spring依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.13.RELEASE</version>
        </dependency>

        <!-- CGLIB的动态代理 -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.2</version>
        </dependency>

        <!--aop切面依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.13.RELEASE</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <!--编译插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

业务接口

public interface IService {
    void add(int id , String name);
    boolean update(int a , int b);
}

业务类

import org.springframework.stereotype.Service;

@Service
public class TeamService implements IService{
    
    @Override
    public void add(int id , String name) {
        //制造异常
        //int num = id/0;
        System.out.println("MyAspect---add---");
    }
    
    @Override
    public boolean update(int a , int b) {
        System.out.println("MyAspect---update---");
        if (a + b > 10) {
            return true;
        }
        return false;
    }
}

切面类

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 * 切面类 XML实现
 * 简洁代理通知
 */
@Component  //创建权限交给 spring容器 进行创建
@Aspect     //aspectj 框架注解 标识该类为切面类
public class MyAspect_XML {
    
    public void before(JoinPoint jp){
        System.out.println("前置通知");
    }
    
    public void afterReturn(Object result){
        System.out.println("后置通知");
    }
    
    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("======================AroundOpen");
        Object obj = pjp.proceed();
        System.out.println("======================AroundEnd");
        return obj;
    }
    
    public void exception(JoinPoint jp, Throwable ex){
        System.out.println("异常通知");
    }
    
    public void myFinally(JoinPoint jp){
        System.out.println("最终通知");
    }
    
}

配置文件 (扫描包,引入代理)

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

    <context:component-scan base-package="com.newAOP" />

<!--    xml实现 代理-->
    <aop:config>
        <aop:pointcut id="pt_ALL" expression="execution(* com.newAOP.service..*.*(..))"/>
        <aop:aspect ref="myAspect_XML">
            <aop:before method="before" pointcut-ref="pt_ALL"/>
            <aop:after-returning method="afterReturn" pointcut-ref="pt_ALL" returning="result"/>
            <aop:after-throwing method="exception" pointcut-ref="pt_ALL" throwing="ex"/>
            <aop:after method="myFinally" pointcut-ref="pt_ALL"/>
<!--            容易出现问题-->
<!--            <aop:around method="around" pointcut-ref="pt_ALL"/>-->
        </aop:aspect>
    </aop:config>

</beans>

测试

@Test
public void test(){
    ApplicationContext ac = new ClassPathXmlApplicationContext("MySpring.xml");
    IService teamService = (IService) ac.getBean("teamService");
    teamService.add(001,"张三");
    System.out.println("\n");
    teamService.update(6, 5);
}

/*运行结果

前置通知
MyAspect---add---
后置通知
最终通知


前置通知
MyAspect---update---
后置通知
最终通知

*/

# 注解实现AOP

对切面类使用指定 注解 定义 切面、切入点 等

注解类型

注解名称 说明
@Aspect 定义 切面(指定 类)
@Pointcut 定义 切入点表达式(指定 类)
@Before 定义 前置通知(指定 方法)
@AfterReturning 定义 后置通知(指定 方法)
@Around 定义 环绕通知(指定 方法)
@AfterThrowing 定义 异常通知(指定 方法)
@After 定义 最终通知(指定 方法,无论异常都会通知)

依赖配置 、业务类 和 业务接口 与上述一致

切面类

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 切面类
 * @author Sans
 */
@Component  //创建权限交给 spring容器 进行创建
@Aspect     //aspectj 框架注解 标识该类为切面类
public class MyAspect {
    /**
     * 切点表达式为:
     *      方法 任意返回类型
     *      指定路径 com.newAOP包
     *      指定包下的所有 子包、子类、类、接口、方法、方法参数
     */
    @Pointcut("execution(* com.newAOP..*.*(..))")
    private void pointCut_all(){ }
    
    /**
     * 前置通知
     * @param jp
     */
    @Before("pointCut_all()")
    public void before(JoinPoint jp){
        System.out.println("======================BeforeOpen");
        System.out.println("前置通知");
        System.out.println("拦截信息:");
        System.out.println("\t方法名称:"+jp.getSignature().getName());
        Object[] args = jp.getArgs();
        if (args.length != 0){
            System.out.println("\t参数格式:"+args.length);
            System.out.println("\t参数列表:");
            for (Object arg : args) {
                System.out.println("\t\t"+arg);
            }
        }
        System.out.println("======================BeforeEnd");
    }
    
    /**
     * 后置通知
     * @param result
     */
    @AfterReturning (value="pointCut_all()",returning = "result")
    public void afterReturn(Object result){
        System.out.println("======================AfterReturnOpen");
        System.out.println("后置通知");
        System.out.println("拦截信息:");
        System.out.println("\t方法返回值:"+result);
        System.out.println("======================AfterReturnEnd");
    }
    
    /**
     * 环绕通知
     * @param pjp
     * @return 方法返回类型
     * @throws Throwable 当前方法运行抛出的异常
     */
    @Around("pointCut_all()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("======================AroundOpen");
        System.out.println("环绕通知");
        Object obj = pjp.proceed();
        System.out.println("方法 返回值为:"+obj);
        System.out.println("======================AroundEnd");
        return obj;
    }
    
    /**
     * 异常通知
     * @param jp 连接点状态
     * @param ex 异常返回
     */
    @AfterThrowing(value = "pointCut_all()",throwing = "ex")
    public void exception(JoinPoint jp,Throwable ex){
        System.out.println("======================ExceptionOpen");
        System.out.println("异常通知");
        //返回连接点的签名(异常)
        System.out.println("异常原因:"+jp.getSignature());
        //返回 throwable 的详细消息字符串
        System.out.println("异常类型:"+ex.getMessage());
        System.out.println("======================ExceptionEnd");
    }
    
    /**
     * 最终通知(无论出现异常都会执行的通知)
     */
    @After("pointCut_all()")
    public void myFinally(JoinPoint jp){
        System.out.println("======================FinallyOpen");
        System.out.println("最终通知");
        System.out.println(jp.getSignature().getName()+" 方法结束!");
        System.out.println("======================FinallyEnd");
    }
    
}

配置文件 (扫描包,切面类注解应用)

<?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"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
	//扫描包。个人配置包路径 为 com.newAOP
    <context:component-scan base-package="com.newAOP" />
	//允许 Spring容器 权限应用
    <aop:aspectj-autoproxy expose-proxy="true"/>
</beans>

测试

@Test
public void test(){
    ApplicationContext ac = new ClassPathXmlApplicationContext("MySpring.xml");
    IService teamService = (IService) ac.getBean("teamService");
    teamService.add(001,"张三");
    System.out.println("\n");
    teamService.update(6, 5);
}

/*运行结果

======================AroundOpen
环绕通知
======================BeforeOpen
前置通知
拦截信息:
	方法名称:add
	参数格式:2
	参数列表:
		1
		张三
======================BeforeEnd
MyAspect---add---
======================AfterReturnOpen
后置通知
拦截信息:
	方法返回值:null
======================AfterReturnEnd
======================FinallyOpen
最终通知
add 方法结束!
======================FinallyEnd
方法 返回值为:null
======================AroundEnd


======================AroundOpen
环绕通知
======================BeforeOpen
前置通知
拦截信息:
	方法名称:update
	参数格式:2
	参数列表:
		6
		5
======================BeforeEnd
MyAspect---update---
======================AfterReturnOpen
后置通知
拦截信息:
	方法返回值:true
======================AfterReturnEnd
======================FinallyOpen
最终通知
update 方法结束!
======================FinallyEnd
方法 返回值为:true
======================AroundEnd

*/

# XML与Annotation 声明区别

xml在外部文件 .xml进行配置;Annotation在类文件中进行配置 无需外部辅助

xml效率一般(需要解析);Annotation效率高

xml需要解析工具进行完成;Annotation无需解析,利用Java反射进行完成

xml易于观察对象关系(业务量较多时);Annotation 不易观察

#spring
上次更新: 2023/03/12, 00:43:49

← Spring IOC Spring拓展→

最近更新
01
HTTPS自动续签
10-21
02
博客搭建-简化版(脚本)
10-20
03
ruoyi-vue-plus-部署篇
07-13
更多文章>
Theme by Vdoing | Copyright © 2019-2024 | 桂ICP备2022009417号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式