spring之为什么要使用AOP(面向切片编程)?

需求1-日志:在程序执行期间追踪正在发生的活动;

需求2-验证:希望计算器只处理正数的运算;

Calculator.java

package com.gong.spring.aop.helloworld;

public interface Calculator {
    int add(int i, int j);
    int sub(int i, int j);
    int mul(int i, int j);
    int div(int i, int j);
}

CalculatorImpl.java

package com.gong.spring.aop.helloworld;

public class CalculatorImpl implements Calculator{

    @Override
    public int add(int i, int j) {
        System.out.println("add begin");
        // TODO Auto-generated method stub
        int result =  i+j;
        System.out.println("add end");
        return result;
    }

    @Override
    public int sub(int i, int j) {
        System.out.println("sub begin");
        // TODO Auto-generated method stub
        int result = i - j;
        System.out.println("sub end");
        return result;
    }

    @Override
    public int mul(int i, int j) {
        System.out.println("mul begin");
        // TODO Auto-generated method stub
        int result = i * j;
        System.out.println("mul end");
        return result;
    }

    @Override
    public int div(int i, int j) {
        System.out.println("div begin");
        // TODO Auto-generated method stub
        int result = i / j;
        System.out.println("div end");
        return result;
    }

}

Main.java

package com.gong.spring.aop.helloworld;

public class Main {
    public static void main(String[] args) {
        Calculator calculator = new CalculatorImpl();
        int i = 2;
        int j = 1;
        int res = calculator.add(i, j);
        System.out.println(res);
        res = calculator.sub(i, j);
        System.out.println(res);
        res = calculator.mul(i, j);
        System.out.println(res);
        res = calculator.div(i, j);
        System.out.println(res);
    }
}

输出:

存在两个问题:

(1)代码混乱:每个方法在处理逻辑核心问题时还要关注其它问题,比如日志和计算。

(2)代码分散:如果日志发生变化,则需要修改所有方法的日志。

第一种解决方法:使用动态代理。

动态代理原理:使用一个代理将对象包装起来,然后调用该代理对象取代原始对象,任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法转到原始的对象上。

CalculatorLoggingImpl.java

package com.gong.spring.aop.helloworld;

public class CalculatorLoggingImpl implements Calculator{

    @Override
    public int add(int i, int j) {
        // TODO Auto-generated method stub
        int result =  i+j;
        return result;
    }

    @Override
    public int sub(int i, int j) {
        // TODO Auto-generated method stub
        int result = i - j;
        return result;
    }

    @Override
    public int mul(int i, int j) {
        // TODO Auto-generated method stub
        int result = i * j;
        return result;
    }

    @Override
    public int div(int i, int j) {
        // TODO Auto-generated method stub
        int result = i / j;
        return result;
    }

}
package com.gong.spring.aop.helloworld;

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

public class CalculatorLoggingProxy {
    public CalculatorLoggingProxy(Calculator target) {
        this.target = target;
    }
    //要代理的对象
    private Calculator target;
    public Calculator getLoggingProxy() {
        Calculator proxy = null;
        //代理对象由哪一个类加载器进行加载
        ClassLoader loader = target.getClass().getClassLoader();
        //代理对象的类型,即其中有哪些方法
        Class [] interfaces = new Class[]{Calculator.class};
        //调用代理对象其中的方法时,该执行的代码
        InvocationHandler h = new InvocationHandler() {
            /*proxy:正在返回的代理对象
             *method::正在被调用的方法
             *args:调用方法时传入的参数
             * */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // TODO Auto-generated method stub
                String methodName = method.getName();
                //日志
                System.out.println(methodName+" begin");
                //执行方法
                Object result = method.invoke(target, args);
                //日志
                System.out.println(methodName+" end");
                return result;
            }
        };
        proxy = (Calculator) Proxy.newProxyInstance(loader, interfaces, h);
        return proxy;
    }
}

Main.java

package com.gong.spring.aop.helloworld;

public class Main {
    public static void main(String[] args) {
        Calculator calculator = new CalculatorLoggingImpl();
        Calculator proxy = new CalculatorLoggingProxy(calculator).getLoggingProxy();
        int i = 2;
        int j = 1;
        int result =proxy.add(i, j);
        System.out.println(result);
        result = proxy.sub(i, j);
        System.out.println(result);
        result = proxy.mul(i, j);
        System.out.println(result);
        result = proxy.div(i, j);
        System.out.println(result);
    }
}

输出:

可以达到同样的效果,但是我们的日志模块只需要关注在代理中如何修改,进而可以影响到普通实现的所有方法。

第二种方式:使用AOP

AOP是对传统OOP(面向对象编程)的一种补充。其主要编程对象是切面,而切面模块化横切关注点。在应用AOP时,仍然需要定义公共功能,但可以明确定义这个功能在哪里,以什么方式应用。并且不必修改受影响的类,这样一来横切关注点就被模块化到特殊对象(切面)里。

AOP的好处:

(1)每个事物逻辑位于一个位置,代码不分散,便于维护和升级;

(2)业务模块更简洁,只包含核心业务代码;

原文地址:https://www.cnblogs.com/xiximayou/p/12161895.html

时间: 2024-08-19 03:43:40

spring之为什么要使用AOP(面向切片编程)?的相关文章

Spring(二):AOP(面向切面编程),Spring的JDBC模板类

1 AOP概述 1.2 什么是AOP 在软件业,AOP为Aspect Oriented Programmig的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. AOP解决了OOP遇到一些问题,采取横向抽取机制,取代了传统

Spring:面向切片编程

在之前我们记录Spring的随笔当中,都是记录的Spring如何对对象进行注入,如何对对象的属性值进行注入,即我们讲解的很大部分都是Spring的其中一个核心概念--依赖注入(或者说是控制翻转,IOC)的方面,那么通过前几天所学的<常用设计模式:代理模式>的学习之后,我们今天来学习一下与代理模式密切相关,或者说是代理模式的一个强大应用的Spring的另一个核心概念--面向切片编程,即AOP(Aspect OrientedProgramming) 首先我们都知道java是一门经典的面向对象的编程

sprint.net(2) AOP面向切面编程,spring.net的环绕通知;Spring.net的AOP通知的四种类型

AOP 有点类似于我们MVC里面的Filter过滤器,例如在MVC里面,如果给一个Action上打一个标签,就可以在这个Action执行之前或者之后,额外的执行一个方法,这个就相当于是面向切面编程. 无侵入式的. (也就是在不改变原来的代码的情况下,来跳转到一个其他的方法,执行完毕后回到主方法..),但是spring.net的AOP更牛叉,只需要在xml里面配置,就可以了,不需要在方法上面打特性的标签,也不需要继承什么类(例如MVC的过滤器是继承了ActionFilterAttribute) 主

深入探索spring技术内幕(七): 配置Spring AOP面向切面编程

一. AOP一些概念 Aspect( 切面 ): 指横切性关注点的抽象即为切面, 它与类相似, 只是两者的关注点不一样, 类是对物体特征的抽象, 而切面横切性关注点的抽象. joinpoint( 连接点 ): 指那些被拦截到的点. 在spring中, 这些点指的是方法, 因为spring只支持方法类型的连接点, 实际上joinpoint还可以是field或类构造器) Pointcut( 切入点 ): 指我们要对那些joinpoint进行拦截的定义. Advice( 通知 ): 指拦截到joinp

spring入门-AOP 面向切面编程

AOP 面向切面编程 在日常开发中最后将业务逻辑定义在一个专门的service包下,而实现定义在service包下的impl包中, 服务接口以IXXXService形式,而服务实现就是XXXService,这就是规约设计 步骤: 1.E:\Users\WorkSpaces\KmwalletApp\spring\aop\test\HelloWorldService.java 继承(implements)xx接口 2.E:\Users\WorkSpaces\KmwalletApp\spring\ao

浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~

简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring框架的,这就说明你有权选择是否要用AOP来完成一些业务. AOP面向切面编程,通过另一种思考的方式,来弥补面向对象编程OOP当中的不足,OOP当中最重要的单元是类,所以万物皆对象,万物皆是 对象类.而在AOP的模块单元中,最基础的单元是切面,切面对切点进行模块化的管理. 最后再提一句:Spring当

Spring:AOP, 面向切面编程

AOP概述 什么是AOP, 面向切面编程 AOP为Aspect Oriented Programming的缩写, 意为:面向切面编程, 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP是OOP的延续, 是函数式编程的一种衍生范型. 利用AOP可以对业务逻辑的各个部分进行隔离, 从而使得业务逻辑各部分之间的耦合度降低, 提高程序的可重用性, 同时提高了开发的效率. - 传统开发模型: 纵向的编程.  面向切面编程: 纵横配合的编程. AOP的作用及优势 作用: 在程序运行期

Javascript aop(面向切面编程)之around(环绕)

Aop又叫面向切面编程,其中“通知”是切面的具体实现,分为before(前置通知).after(后置通知).around(环绕通知),用过spring的同学肯定对它非常熟悉,而在js中,AOP是一个被严重忽视的技术点.但是利用aop可以有效的改善js代码逻辑,比如前端框架dojo和yui3中AOP则被提升至自定义事件的一种内在机制,在源码中随处可见.得益于这种抽象使得dojo的自定义事件异常强大和灵活.dojo中aop的实现在dojo/aspect模块中,主要有三个方法:before.after

java aop面向切面编程

最近一直在学java的spring boot,一直没有弄明白aop面向切面编程是什么意思.看到一篇文章写得很清楚,终于弄明白了,原来跟python的装饰器一样的效果.http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html Aspect Oriented Programming  面向切面编程.解耦是程序员编码开发过程中一直追求的.AOP也是为了解耦所诞生. 具体思想是:定义一个切面,在切面的纵向定义处理方法,处理完成之后,回

AOP:面向切面编程

AOP:面向切面编程(Aspect-Oriented Programming)      AOP可以说是对OOP的补充和完善.OOP引入封装.继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合.当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力.也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系.例如日志功能.日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系.在OOP设计中,它导致了大量代码的重复,而不利于各个模块的