AOP

AOP:面向切面编程,相对于OOP面向对象编程。Spring的AOP的存在目的是为了解耦。AOP可以让一组类共享相同的行为。在OOP中只能通过继承类和实现接口,来使代码的耦合度增强,且类继承只能为单继承,阻碍更多行为添加到一组类上,AOP弥补了OOP的不足。

Spring支持AspectJ的注解式切面编程。

(1)使用@Aspect声明是一个切面。

(2)使用@After、@Before、@Around定义建言(advice),可直接将拦截规则(切点)作为参数。

(3)其中@After、@Before、@Around参数的拦截规则为切点(PointCut),为了使切点复用,可使用@PointCut专门定义拦截规则,然后在@After、@Before、@Around的参数中调用。

(4)其中符合条件的每一个被拦截处为连接点(JoinPoint)。

本例将演示基于注解拦截和基于方法规则拦截两种方式,演示一种模拟记录操作的日志系统的实现。其中注解式拦截能够很好地控制要拦截的粒度和获得更丰富的信息,Spring本身在事务处理(@Transcational)和数据缓存(@Cacheable等)上面都使用此种形式的拦截。

springboot 面向切面AOP_AOP

添加spring aop支持及AspectJ依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.5</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.5</version>
        </dependency>

编写拦截规则的注解

Action.java

package com.shrimpking;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2023/6/7 18:20
 * @Target可以使用在方法上
 * @Retention 策略是运行时
 * @Documented 可以生成文档标注
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Action
{
    String name();
}

代码解释

这里讲下注解,注解本身是没有功能的,就和xml一样。注解和xml都是一种元数据,元数据即解释数据的数据,这就是所谓配置。

注解的功能来自用这个注解的地方。

编写使用注解的类

DemoAnnotationService.java

package com.shrimpking;

import org.springframework.stereotype.Service;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2023/6/7 18:22
 */
@Service
public class DemoAnnotationService
{
    @Action(name = "注解式拦截的add方法")
    public void add()
    {
        //...
    }
}

编写使用方法规则被拦截类

DemoMethodService.java

package com.shrimpking;

import org.springframework.stereotype.Service;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2023/6/7 18:31
 */
@Service
public class DemoMethodService
{
    public void addOther()
    {
        //...
    }

    public void update()
    {
        //...
    }
}

编写切面

LogAspect.java

package com.shrimpking;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2023/6/7 18:31
 * @Aspect注解声明一个切面
 * @Component让此切面成为Spring容器管理的Bean
 */
@Aspect
@Component
public class LogAspect
{
    /**
     * @PointCut注解声明切点,规则是使用了Action注解的均切入
     */
    @Pointcut("@annotation(com.shrimpking.Action)")
    public void pointCut()
    {

    }

    /**
     * 使用pointCut切入点
     * @param joinPoint
     */
    @After("pointCut()")
    public void after(JoinPoint joinPoint)
    {
        //获取连接点的签名,强转为方法签名
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        //获取方法名
        Method method = methodSignature.getMethod();
        //获取方法上的注解
        Action annotation = method.getAnnotation(Action.class);
        //输出注解名称
        System.out.println("注解式拦截 " + annotation.name());
    }

    /**
     * 自定义切入规则,是DemoMethodService类下的所有方法
     * @param joinPoint
     */
    @Before("execution(* com.shrimpking.DemoMethodService.*(..))")
    public void before(JoinPoint joinPoint)
    {
        //获取连接点的签名,强转为方法签名
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        //获取方法名
        Method method = methodSignature.getMethod();
        //输出方法名称
        System.out.println("方法式拦截 " +method.getName());
    }

}

代码解释

①通过@Aspect注解声明一个切面。

②通过@Component让此切面成为Spring容器管理的Bean。

③通过@PointCut注解声明切点。

④通过@After注解声明一个建言,并使用@PointCut定义的切点。

⑤通过反射可获得注解上的属性,然后做日志记录相关的操作,下面的相同。

⑥通过@Before注解声明一个建言,此建言直接使用拦截规则作为参数。

配置类

AopConfig.java

package com.shrimpking;

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

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2023/6/7 18:46
 * @EnableAspectJAutoProxy注解开启Spring对AspectJ代理的支持
 */
@Configuration
@ComponentScan("com.shrimpking")
@EnableAspectJAutoProxy
public class AopConfig
{

}

代码解释

①使用@EnableAspectJAutoProxy注解开启Spring对AspectJ代理的支持。

运行

package com.shrimpking;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

@SpringBootApplication
public class Springboot41AopApplication
{

    public static void main(String[] args)
    {
        //SpringApplication.run(Springboot41AopApplication.class, args);
        AnnotationConfigApplicationContext context
                = new AnnotationConfigApplicationContext(AopConfig.class);
        DemoAnnotationService demoAnnotationService
                = context.getBean(DemoAnnotationService.class);
        demoAnnotationService.add();

        DemoMethodService demoMethodService
                = context.getBean(DemoMethodService.class);
        demoMethodService.addOther();
        demoMethodService.update();

        context.close();
    }

}

结果如图

springboot 面向切面AOP_java_02

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Spring