博客
关于我
Spring篇-AOP
阅读量:146 次
发布时间:2019-02-27

本文共 3425 字,大约阅读时间需要 11 分钟。

AOP(面向切面编程)是一种软件开发的编程范式,旨在通过动态代理和切面技术,隔离系统中的关注点,提升系统的可维护性和可扩展性。AOP通过在不修改源代码的情况下,动态地在主干功能中注入新的功能,降低了代码之间的耦合度,提高了开发效率。

AOP的概念

AOP的核心思想是通过在业务逻辑的各个部分(即切面)中插入额外的逻辑(通知),从而实现对系统流程的监控、记录或修改。这种方式使得代码的耦合度降低,系统的可维护性提高,开发效率也随之提升。

AOP的通俗描述是:在不修改现有代码的情况下,通过动态方式在主干功能中注入新功能。这意味着可以在不影响现有业务逻辑的情况下,添加日志记录、事务管理、权限验证等功能。

AOP底层原理

AOP的实现通常依赖于动态代理技术。动态代理在Java中有两种实现方式:

  • 基于接口的动态代理(JDK动态代理):适用于目标对象实现了接口的情况。Java的Proxy类提供了newProxyInstance方法来创建动态代理对象。这种方式通过生成一个代理类,代理目标对象的方法调用。

  • 基于类的动态代理(CGLIB动态代理):适用于目标对象没有接口的情况。CGLIB动态代理通过生成一个继承目标类的子类来实现动态代理。

  • JDK动态代理代码实现

    在实际开发中,JDK动态代理是最常用的实现方式。以下是使用JDK动态代理实现AOP的一种常见做法:

    代码实现

    public interface UserDao {    int add(int a, int b);    String update(String id);}public class UserDaoImpl implements UserDao {    @Override    public int add(int a, int b) {        System.out.println("执行了add方法");        return a + b;    }    @Override    public String update(String id) {        System.out.println("执行了update方法");        return id;    }}public class JDKProxyTest {    public static void main(String[] args) {        Class[] interfaces = {UserDao.class};        UserDao dao = (UserDao) Proxy.newProxyInstance(            JDKProxyTest.class.getClassLoader(),            interfaces,            new UserDaoProxy(new UserDaoImpl())        );        System.out.println(dao.add(10, 20));        System.out.println("---------------------------------------------");        System.out.println(dao.update("cVzhanshi"));    }}public class UserDaoProxy implements InvocationHandler {    private Object obj;    public UserDaoProxy(Object obj) {        this.obj = obj;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args)        throws Throwable {        System.out.println("方法之前执行...." + method.getName() + " :传递的参数... " + Arrays.toString(args));        Object res = method.invoke(obj, args);        System.out.println("方法之后执行...." + obj);        return res;    }}

    运行效果

    运行上述代码,可以看到输出结果如下:

    方法之前执行....add :传递的参数... [10, 20]执行了add方法11方法之后执行....UserDaoImpl@16:29----------------------------------------------方法之前执行....update :传递的参数... [cVzhanshi]执行了update方法cVzhanshi方法之后执行....UserDaoImpl@16:29

    AOP术语

    在AOP中,主要涉及以下术语:

  • 连接点:系统中能够被增强的方法或代码位置。

  • 切入点:实际被增强的方法或代码位置。

  • 通知:在增强的逻辑中,用于实现特定功能的代码块。通知有多种类型:

    • 前置通知:在方法执行前调用。
    • 后置通知:在方法执行后调用(返回通知)。
    • 最终通知:在方法执行后总是调用。
    • 异常通知:在方法抛出异常时调用。
    • 环绕通知:在方法执行前后都有逻辑。
  • 切面:指将通知应用到切入点的过程。

  • AOP操作

    在实际项目中,Spring框架通常基于AspectJ实现AOP操作。AspectJ是一个独立的AOP框架,与Spring无关,但常常与Spring一起使用。

    基于注解的AOP操作

    在使用AspectJ实现AOP时,主要使用以下注解:

  • @Before:表示前置通知。
  • @AfterReturning:表示返回通知。
  • @After:表示最终通知。
  • @AfterThrowing:表示异常通知。
  • @Around:表示环绕通知。
  • 以下是一个简单的示例:

    public class User {    public void add() {        System.out.println("执行add方法");    }}public class UserProxy {    @Before(value = "execution(*User.add())")    public void before() {        System.out.println("方法执行前....");    }    @After(value = "execution(*User.add())")    public void after() {        System.out.println("方法执行后....");    }    @Around(value = "execution(*User.add())")    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {        System.out.println("环绕前....");        proceedingJoinPoint.proceed();        System.out.println("环绕后....");    }}

    在Spring中配置:

    配置文件实现

    在Spring的配置文件中,可以通过 <aop:config>标签来配置切面。以下是一个简单的示例:

    补充

  • 相同切入点抽取:当多个增强类使用相同的切入点时,可以通过创建公共切入点方法来提高代码复用性。

  • 切面优先级:在多个增强类中定义相同的切入点时,可以通过在增强类上添加@Order注解来设置优先级,优先级越小的切面优先生效。

  • 通过以上方法,开发者可以灵活地使用AOP技术来实现系统的各项需求,提升系统的可维护性和扩展性。

    转载地址:http://rrkb.baihongyu.com/

    你可能感兴趣的文章
    NotImplementedError: Cannot copy out of meta tensor; no data! Please use torch.nn.Module.to_empty()
    查看>>
    npm run build 失败Compiler server unexpectedly exited with code: null and signal: SIGBUS
    查看>>
    npm WARN deprecated core-js@2.6.12 core-js@<3.3 is no longer maintained and not recommended for usa
    查看>>
    npm和yarn的使用对比
    查看>>
    npm报错unable to access ‘https://github.com/sohee-lee7/Squire.git/‘
    查看>>
    npm的问题:config global `--global`, `--local` are deprecated. Use `--location=global` instead 的解决办法
    查看>>
    NR,NF,FNR
    查看>>
    nrf开发笔记一开发软件
    查看>>
    NSDateFormatter的替代方法
    查看>>
    NSOperation基本操作
    查看>>
    NSSet集合 无序的 不能重复的
    查看>>
    NT AUTHORITY\NETWORK SERVICE 权限问题
    查看>>
    ntko文件存取错误_苹果推送 macOS 10.15.4:iCloud 云盘文件夹共享终于来了
    查看>>
    nullnullHuge Pages
    查看>>
    numpy 用法
    查看>>
    Numpy如何使用np.umprod重写range函数中i的python
    查看>>
    oauth2-shiro 添加 redis 实现版本
    查看>>
    OAuth2.0_JWT令牌-生成令牌和校验令牌_Spring Security OAuth2.0认证授权---springcloud工作笔记148
    查看>>
    OAuth2.0_JWT令牌介绍_Spring Security OAuth2.0认证授权---springcloud工作笔记147
    查看>>
    OAuth2.0_介绍_Spring Security OAuth2.0认证授权---springcloud工作笔记137
    查看>>