欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

AOP详解与实例第一章

程序员文章站 2024-03-25 21:14:16
...

AOP介绍

AOP面向切面编程,主要解决特定问题,如:代码重复问题、关注点分离(
水平分离:展示层 ->服务层->持久层
垂直分离:模块划分 订单、库存等模块
切面分离:分离功能性与非功能性需求)

AOP优点

  1. 集中处理某一个关键点/横切逻辑
  2. 可以很方便地添加/删除关注点
  3. 侵入性少,增加代码可读性及可维护性

AOP使用场景

  1. 权限控制
  2. 缓存控制
  3. 事物控制
  4. 日志控制
  5. 性能监控
  6. 分布式追踪
  7. 异常处理

小试牛刀

需求背景产品添加或删除操作只有管理员才可以进行,下面我们就普通实现 VS AOP实现。

新建一个项目

https://start.spring.io/

配置如图
AOP详解与实例第一章
pom.xml添加依赖

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

代码实现结构如下
AOP详解与实例第一章

实体类

package com.demo.aop.entity;

public class Product {
    private String id;
    private String name;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

方便切换用户

package com.demo.aop.security;

/**
 * 方便切换用户
 */
public class CurrentUserHolder {
    private static final ThreadLocal<String> holder = new ThreadLocal<>();

    public static String  get() {
        return holder.get() == null ? "unKnown":holder.get();
    }

    public static void set(String user){
        holder.set(user);
    }
}

权限类,设置你的权限

package com.demo.aop.sevice;

import com.demo.aop.security.CurrentUserHolder;
import org.springframework.stereotype.Component;

@Component
public class AuthService {
    //检查权限
    public void checkAccess(){
        String user = CurrentUserHolder.get();
        if(!"admin".equals(user)){
            throw new RuntimeException("操作不允许!");
        }
    }
}

AOP 注解方式

package com.demo.aop.annotation;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AdiminOnly {
}

//------------------------分割线--------------------------------------

package com.demo.aop.security;

import com.demo.aop.sevice.AuthService;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class SecurityAspect {
    @Autowired
    AuthService authService;

    @Pointcut(value = "@annotation(com.demo.aop.annotation.AdiminOnly)")
    public void adminOnly(){}

    @Before("adminOnly()")
    public void check(){
        authService.checkAccess();
    }
}

package com.demo.aop.sevice;

import com.demo.aop.annotation.AdiminOnly;
import com.demo.aop.entity.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 模拟现实场景业务调用
 */
@Service
public class ProductService {
    //传统方法
    @Autowired
    AuthService authService;

    //模拟新增操作 传统方法
    public void insert(Product product){
        authService.checkAccess();
        System.out.println("新增操作成功!");
    }

    //删除造成 AOP 注解方法 只需注解即可
    @AdiminOnly
    public void delete(String id){
        System.out.println("删除操作成功!");
    }
}

演示

package com.demo.aop.sevice;


import com.demo.aop.entity.Product;
import com.demo.aop.security.CurrentUserHolder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;



@SpringBootTest
class ProductServiceTest{

    @Autowired
    ProductService productService;

    //传统方式
    @Test
    public void insert() {
        CurrentUserHolder.set("tom");
        productService.insert(new Product());
    }

    //切面方式
    @Test
    public void delete() {
        CurrentUserHolder.set("admin");
        productService.delete("1");
    }
}

运行:
运行传统方法insert,出现错误,如果想要正确把tom 改为 admin 测试即可
AOP详解与实例第一章
运行AOP注解方式如下,如果想要错误把admin改为tom即可
AOP详解与实例第一章
是不是初步了解了呢,下面我讲下语法使用等介绍,请看 “AOP详解与实例第二章” 。

相关标签: aop spring