JDK 动态代理

java.lang.reflect.Proxy 创建代理对象,调用下面的方法实现动态代理。
newProxyInstance()

  1. 参数1:ClassLoader
  2. 参数2:interfaces[]
  3. 参数3:InvocationHandler 接口实现增强部分功能; ```java package io.zsy.annotation.aop;

import io.zsy.annotation.dao.UserDao; import io.zsy.annotation.dao.UserMapper;

import java.lang.reflect.Proxy;

/**

  • @author zhangshuaiyin
  • @date 2022/4/25 20:28 */ public class JdkProxy { public static void main(String[] args) {

    1. Class<?>[] interfaces = {UserDao.class};
    2. UserDao userMapper = new UserMapper();
    3. UserDao userDao = (UserDao) Proxy.newProxyInstance(JdkProxy.class.getClassLoader(), interfaces, (proxy, method, params) -> {
    4. // 执行代理方法之前
    5. System.out.println("JdkProxy - 动态代理方法执行前执行逻辑");
    6. // 被代理的方法执行, proxy是被代理的对象,method是被代理对象的方法
    7. method.invoke(userMapper, params);
    8. // 执行代理方法之后
    9. System.out.println("JdkProxy - 动态代理方法执行后执行逻辑");
    10. return proxy;
    11. });
    12. userDao.add();

    } } ```

    AOP 术语

  1. 连接点:可以增强的方法
  2. 切入点:实际被增强的方法
  3. 通知:实际增强的逻辑部分(增强)
    1. 前置通知
    2. 后置通知
    3. 环绕通知
    4. 异常通知
    5. 最终通知
  4. 切面:把通知应用到切入点的过程

引入依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
</dependency>

<!-- 实现 AOP -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
</dependency>

Spring AOP

Spring 框架一般是基于 AspectJ 实现 AOP 操作。AspectJ 不是 Spring 组成部分,独立于 AOP 框架。一般把 AspectJ 和 Spring 一起使用完成 AOP 操作。

  1. 基于 xml 配置方式
  2. 基于注解方式

    切入点表达式

    切入点表达式指定了对哪个类的哪个方法进行增强。
    语法结构: execution([权限修饰符][返回类型][全限定类名][方法名称]([参数列表]))
    示例:

  3. 对 io.zsy.dao.BookDao 类进行增强:execution(* io.zsy.dao.BookDao.add(..))

  4. 对所有方法进行增强:execution(* io.zsy.dao.BookDao.*(..))
  5. 对 io.zsy.dao 包下的所有类的所有方法增强:execution(* io.zsy.dao.*.*(..))

    注解方式实现

  6. 创建被代理类和代理对象 ```java package io.zsy.annotation.aop.anno;

import org.springframework.stereotype.Component;

/**

  • @author zhangshuaiyin
  • @date 2022/4/25 21:01 */ @Component public class User { public void add() {
     System.out.println("User add..");
    
    } } java package io.zsy.annotation.aop.anno;

import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component;

/**

  • @author zhangshuaiyin
  • @date 2022/4/25 21:01 */ @Aspect @Component public class UserProxy {

    @Pointcut(value = “execution(* io.zsy.annotation.aop.anno.User.add(..))”) public void pointCut() { }

    @Before(“pointCut()”) public void before() {

     System.out.println("UserProxy before - 前置通知");
    

    }

    @After(“execution(* io.zsy.annotation.aop.anno.User.add(..))”) public void after() {

     System.out.println("UserProxy after - 后置通知");
    

    }

    @Around(“execution(* io.zsy.annotation.aop.anno.User.add(..))”) public Object around(ProceedingJoinPoint joinPoint) throws Throwable {

     System.out.println("UserProxy around - 环绕通知 方法执行前");
     Object result = joinPoint.proceed();
     System.out.println("UserProxy around - 环绕通知 方法执行后");
     return result;
    

    }

    @AfterThrowing(“execution(* io.zsy.annotation.aop.anno.User.add(..))”) public void afterThrowing() {

     System.out.println("UserProxy afterThrowing - 异常通知");
    

    }

    @AfterReturning(“execution(* io.zsy.annotation.aop.anno.User.add(..))”) public void afterReturning() {

     System.out.println("UserProxy afterReturning - 最终通知");
    

    } }


2. 配置文件开启组件扫描和AspectJ
```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: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.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.xsd">

    <!-- 开启组件扫描,创建有注解的 bean 对象 -->
    <context:component-scan base-package="io.zsy.annotation.aop.anno"/>
    <!-- 开启 Aspect 生成代理对象 -->
    <aop:aspectj-autoproxy/>

</beans>
  1. 测试 ```java package io.zsy.annotation;

import io.zsy.annotation.aop.anno.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;

/**

  • @author zhangshuaiyin
  • @date 2022/4/25 21:08 */ public class AopTests {

    @Test public void testAopAnno() {

     ApplicationContext context = new ClassPathXmlApplicationContext("aop-anno.xml");
     User user = context.getBean("user", User.class);
     user.add();
    

    } } ``` 其他注解:

  1. @Order:设置代理增强 AspectJ 类的的优先级

    完全注解实现

    ```java package io.zsy.annotation.aop.config;

import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**

  • @author zhangshuaiyin
  • @date 2022/4/25 21:28 */ @Configuration @ComponentScan(basePackages = {“io.zsy.annotation.aop.anno”}) @EnableAspectJAutoProxy(proxyTargetClass = true) public class AopConfig { }

    测试
    ```java
    @Test
    public void testAopAllAnno() {
     ApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);
     User user = context.getBean("user", User.class);
     user.add();
    }
    

    配置文件实现

    ```xml <?xml version=”1.0” encoding=”UTF-8”?>

       <aop:before method="before" pointcut-ref="p"/>
    

```