Spring AOP 面向切面编程,OOP面向对象编程,将程序中所有参与模块都抽象成对象,然后通过对象之间的相互调用完成需求。

AOP是OOP的一种补充,是在另外一个维度上抽象出对象,具体是指程序运行时动态地将非业务代码切入到业务代码中,从而实现代码的解耦合,将非业务代码抽象成一个对象,对该对象进行编程就是面向切面编程思想。

AOP的优点:

  1、大大降低模块之间的耦合性;

  2、提高代码的维护性;

  3、提高代码的复用性;

  4、集中管理非业务代码,便于维护;

  5、业务代码不受非业务代码的影响,逻辑更加清晰;

JDK代理方式

委托类

package com.sunjian.aop;

/**
 * @author sunjian
 * @date 2020/3/16 8:12
 */
public interface Cal {
    public int add(int num1, int num2);
    public int sub(int num1, int num2);
    public int mul(int num1, int num2);
    public int div(int num1, int num2);
}
package com.sunjian.aop;

/**
 * @author sunjian
 * @date 2020/3/16 8:13
 */
public class MyCal implements Cal {
    public int add(int num1, int num2) {
        int result = num1 + num2;
        return result;
    }

    public int sub(int num1, int num2) {
        int result = num1 - num2;
        return result;
    }

    public int mul(int num1, int num2) {
        int result = num1 * num2;
        return result;
    }

    public int div(int num1, int num2) {
        int result = num1 / num2;
        return result;
    }
}

代理类

package com.sunjian.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

/**
 * @author sunjian
 * @date 2020/3/16 8:14
 */
public class MyInvocationHandler implements InvocationHandler {
    private Object object = null; // 委托对象

    // 返回代理对象
    public Object bind(Object object){
        this.object = object;
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(method.getName() + "的参数是 " + Arrays.toString(args));
        Object result = method.invoke(this.object, args);
        System.out.print(method.getName() + "的结果是 ");
        return result;
    }
}

测试类

package com.sunjian.aop;

/**
 * @author sunjian
 * @date 2020/3/16 8:19
 */
public class Test {
    public static void main(String[] args) {
        Cal cal = new MyCal();
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
        Cal proxy = (Cal) myInvocationHandler.bind(cal);
        System.out.println(proxy.add(10,3));
        System.out.println(proxy.sub(10,3));
        System.out.println(proxy.mul(10,3));
        System.out.println(proxy.div(10,3));
    }
}

打印结果

add的参数是 [10, 3]
add的结果是 13

sub的参数是 [10, 3]
sub的结果是 7

mul的参数是 [10, 3]
mul的结果是 30

div的参数是 [10, 3]
div的结果是 3

Spring 方式
  AOP 核心概念

    1、切面对象,根据切面抽象出来的对象,在实现类 MyCal 的所有方法中加入日志部分,抽象成一个切面对象LoggerAspect;

    2、通知,切面对象的具体代码,即非业务代码,loggerAspect打印日志的各种操作;

    3、目标,被切割的对象,MyCal;

    4、代理,切面对象,通知,目标混合之后的产物,Spring通过JDK动态代理创建,真正执行代码的对象;

    5、连接点,需要被横切的位置,即通知要插入业务代码的具体位置;

委托类

package com.sunjian.aop;

/**
 * @author sunjian
 * @date 2020/3/16 8:12
 */
public interface Cal {
    public int add(int num1, int num2);
    public int sub(int num1, int num2);
    public int mul(int num1, int num2);
    public int div(int num1, int num2);
}
package com.sunjian.aop;

import org.springframework.stereotype.Component;

/**
 * @author sunjian
 * @date 2020/3/16 8:13
 */
@Component("myCal")
public class MyCal implements Cal {
    public int add(int num1, int num2) {
        int result = num1 + num2;
        return result;
    }

    public int sub(int num1, int num2) {
        int result = num1 - num2;
        return result;
    }

    public int mul(int num1, int num2) {
        int result = num1 * num2;
        return result;
    }

    public int div(int num1, int num2) {
        int result = num1 / num2;
        return result;
    }
}

代理类

package com.sunjian.aop;

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

import java.util.Arrays;

/**
 * @author sunjian
 * @date 2020/3/16 9:20
 */
@Aspect
@Component
public class LoggerAspect {
    @Before(value = "execution(public int com.sunjian.aop.MyCal.*(..))")
    public void before(JoinPoint joinPoint) {
        // 获取方法名
        String name = joinPoint.getSignature().getName();
        // 参数列表
        String args = Arrays.toString(joinPoint.getArgs());
        System.out.println(name + "的参数是 " + args);
    }

    @AfterReturning(value = "execution(public int com.sunjian.aop.MyCal.*(..))", returning = "result")
    public void after(JoinPoint joinPoint, Object result) {
        System.out.println(joinPoint.getSignature().getName() + "方法的执行结果是 " + result);
    }

    @After(value = "execution(public int com.sunjian.aop.MyCal.*(..))")
    public void after(JoinPoint joinPoint){
        System.out.println(joinPoint.getSignature().getName() + "业务执行完毕...");
    }

    @AfterThrowing(value = "execution(public int com.sunjian.aop.MyCal.*(..))", throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, Exception e){
        System.out.println(joinPoint.getSignature().getName() + "方法抛出异常 " + e);
    }
}

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">

    <!-- 自动扫描 -->
    <context:component-scan base-package="com.sunjian"></context:component-scan>

    <!-- 为目标类自动生成代理对象 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

  将⽬标类和切⾯类交给 IoC 容器管理, IoC 容器会自动创建实例化对象,结合 JDK 动态代理,自动实现 InvocationHandler 接口,整合完成业务代码和非业务代码的解耦合。

  context:component-scan   将 com.sunjian 包中的所有类扫描到 IoC 容器中,需要结合 @Component 注解完成。
  aop:aspectj-autoproxy       Spring 会结合切面类和目标类自动生成动态代理对象,代理对象完成非业务代码(日志打印)。

测试类

package com.sunjian.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author sunjian
 * @date 2020/3/16 8:19
 */
public class Test {
    public static void main(String[] args) {

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("aop.xml");
        Cal cal = (Cal) applicationContext.getBean("myCal");
        System.out.println(cal.add(10,3));
        System.out.println(cal.sub(10,3));
        System.out.println(cal.mul(10,3));
        System.out.println(cal.div(10,3));

    }
}

打印结果

add的参数是 [10, 3]
add业务执行完毕...
add方法的执行结果是 13
13

sub的参数是 [10, 3]
sub业务执行完毕...
sub方法的执行结果是 7
7

mul的参数是 [10, 3]
mul业务执行完毕...
mul方法的执行结果是 30
30

div的参数是 [10, 3]
div业务执行完毕...
div方法的执行结果是 3
3

另:同时给一个目标添加多个切面时的执行顺序,实现 org.springframework.Ordered 接口, ordered 越⼩最先执⾏。

Spring框架——AOP的更多相关文章

  1. spring框架 AOP核心详解

    AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...

  2. 跟着刚哥学习Spring框架--AOP(五)

    AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入 ...

  3. spring框架aop用注解形式注入Aspect切面无效的问题解决

    由于到最后我的项目还是有个邪门的错没解决,所以先把文章大概内容告知: 1.spring框架aop注解扫描默认是关闭的,得手动开启. 2.关于Con't call commit when autocom ...

  4. Spring框架——AOP代理

    我们知道AOP代理指的就是设计模式中的代理模式.一种是静态代理,高效,但是代码量偏大:另一种就是动态代理,动态代理又分为SDK下的动态代理,还有CGLIB的动态代理.Spring AOP说是实现了AO ...

  5. Spring框架-AOP详细学习[转载]

    参考博客:https://blog.csdn.net/qq_22583741/article/details/79589910#4-%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85% ...

  6. Spring框架 AOP面向切面编程(转)

    一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnbl ...

  7. 10 Spring框架 AOP (三) Spring对AspectJ的整合

    上两节我们讲了Spring对AOP的实现,但是在我们的开发中我们不太使用Spring自身的对AOP的实现,而是使用AspectJ,AspectJ是一个面向切面的框架,它扩展了Java语言.Aspect ...

  8. Spring框架AOP学习总结(下)

    目录 1. AOP 的概述 2. Spring 基于AspectJ 进行 AOP 的开发入门(XML 的方式): 3.Spring 基于AspectJ 进行 AOP 的开发入门(注解的方式): 4.S ...

  9. 08 Spring框架 AOP (一)

    首先我们先来介绍一下AOP: AOP(Aspect Orient Programming),面向切面编程,是面向对象编程OOP的一种补充.面向对象编程是从静态角度考虑程序的结构,面向切面编程是从动态的 ...

  10. 09 Spring框架 AOP (二) 高级用法

    上一篇文章我们主要讲了一点关于AOP编程,它的动态考虑程序的运行过程,和Spring中AOP的应用,前置通知,后置通知,环绕通知和异常通知,这些都是Spring中AOP最简单的用法,也是最常用的东西, ...

随机推荐

  1. jsp页面jstl标签库失效问题

    可能是版本低的问题,启用jstl即可解决(仅供参考) <%@ page isELIgnored="false"%>

  2. python Post 登录 cookies 和session

    def post_name(): print('\npost name') # http://pythonscraping.com/pages/files/form.html data = {'fir ...

  3. Hexo和github搭建个人博客 - 朱晨

    GitHub账号 mac/pc 环境 12 node.jsgit 创建GitHub仓库 登陆GitHub,创建一个新的Respository Repository name叫做{username}.g ...

  4. iOS 客户端与服务端做时间同步

    需求 我们做客户端的时候,有时会需要对客户端与服务器的时间进行同步,比如抢购活动.倒计时等.这时我们要考虑如何准备地与服务器的时间进行同步,同时防止用户本地的时间有误差时导致的问题. 分析 描述 为了 ...

  5. android编译架构之添加C项目

    1.  增加一个项目与android编译中枢息息相关.特别需要告诉编译中枢的一些特别信息. 例如: A 这个项目target名字是什么 B 这个项目编译类型是什么,bin?c?lib?or jar? ...

  6. Microsoft Translator发布粤语文本翻译

    今天,Microsoft Translator发布了粤语的文本翻译,新的语言增加将继续丰富微软翻译产品的生态系统*,让更多组织和个人能够快速且高效地实现翻译应用.在中国,大有约5500万人使用粤语(语 ...

  7. 你的胃能Hold住未来的食物吗?

    ​ 如果你是一名美食客,那么一定会发现现在越来越多的食物已经发生了翻天覆地的变化,很多食物正在以我们未知的形式出现在生活中,其中最大的莫过于分子美食.你想过吗?当食物发生改变的时候,你的胃是否能够Ho ...

  8. go语言指南之斐波纳契闭包

    练习:斐波纳契闭包 让我们用函数做些好玩的事情. 实现一个 fibonacci 函数,它返回一个函数(闭包),该闭包返回一个斐波纳契数列 `(0, 1, 1, 2, 3, 5, ...)`. 这是一个 ...

  9. Asp.Net Core EndPoint 终点路由工作原理解读

    一.背景 在本打算写一篇关于Identityserver4 的文章时候,确发现自己对EndPoint -终结点路由还不是很了解,故暂时先放弃了IdentityServer4 的研究和编写:所以才产生了 ...

  10. redis01

    1.redis 1)cookie与session session本质上也是cookie,cookie携带session返回给服务端 redis是一个存储数据库 redis读写快速,使用简单,常用于存储 ...