15Spring AOP基础

为什么需要AOP?

先来看一段代码:

package com.cn.spring.aop.helloworld;
//加减乘除的接口类
public interface ArithmeticCalculator {
    int add(int i, int j);
    int sub(int i, int j);
    int mul(int i, int j);
    int div(int i, int j);
}
package com.cn.spring.aop.helloworld;

//实现类
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
    @Override
    public int add(int i, int j) {
        int result = i + j;
        return result;
    }

    @Override
    public int sub(int i, int j) {
        int result = i - j;
        return result;
    }

    @Override
    public int mul(int i, int j) {
        int result = i * j;
        return result;
    }

    @Override
    public int div(int i, int j) {
        int result = i / j;
        return result;
    }
}

现在问题来了:

现在需要在程序执行期间追踪正在发生的活动?

代码如下:

package com.cn.spring.aop.helloworld;

//实现类
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
    @Override
    public int add(int i, int j) {
        System.out.println("The method add begins with[" + i + "," + j + "]");
        int result = i + j;
        System.out.println("The method add ends with[" + i + "," + j + "]");
        return result;
    }

    @Override
    public int sub(int i, int j) {
        System.out.println("The method sub begins with[" + i + "," + j + "]");
        int result = i - j;
        System.out.println("The method sub ends with[" + i + "," + j + "]");
        return result;
    }

    @Override
    public int mul(int i, int j) {
        System.out.println("The method mul begins with[" + i + "," + j + "]");
        int result = i * j;
        System.out.println("The method mul ends with[" + i + "," + j + "]");
        return result;
    }

    @Override
    public int div(int i, int j) {
        System.out.println("The method div begins with[" + i + "," + j + "]");
        int result = i / j;
        System.out.println("The method div ends with[" + i + "," + j + "]");
        return result;
    }
}

如果还希望计算器的加减乘除只能处理整数的运算呢,又需要在ArithmeticCalculatorImpl 实现类中添加代码进行验证,每添加一个需求,都要去添加类似的代码。

使得代码冗余且维护性低。

那如何用AOP来解决呢?

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

先来看下代理是如何来实现的:

package com.cn.spring.aop.helloworld;
//加减乘除的接口类
public interface ArithmeticCalculator {
    int add(int i, int j);
    int sub(int i, int j);
    int mul(int i, int j);
    int div(int i, int j);
}
package com.cn.spring.aop.helloworld;

//实现类
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
    @Override
    public int add(int i, int j) {
        int result = i + j;
        return result;
    }

    @Override
    public int sub(int i, int j) {
        int result = i - j;
        return result;
    }

    @Override
    public int mul(int i, int j) {
        int result = i * j;
        return result;
    }

    @Override
    public int div(int i, int j) {
        int result = i / j;
        return result;
    }
}
package com.cn.spring.aop.helloworld;

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

public class ArithmeticCalculatorLoggingProxy {
    //要代理的对象
    private ArithmeticCalculator target;

    public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target) {
        this.target = target;
    }

    public ArithmeticCalculator getLoggingProxy() {
        ArithmeticCalculator proxy = null;

        //代理对象由哪一个类加载器负责加载
        ClassLoader loader = target.getClass().getClassLoader();
        //代理对象的类型,即其中有哪些方法
        Class[] interfaces = new Class[]{ArithmeticCalculator.class};

        InvocationHandler handler = new InvocationHandler() {
            /**
             *
             * @param proxy 正在返回的那个代理对象,一般情况下,在invoke方法中都不使用该对象
             * @param method 正在被调用的方法
             * @param args 调用方法时,传入的参数
             * @return
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String methodName = method.getName();
                System.out.println("The methed " + methodName + "begins with " + Arrays.asList(args));
                Object result = method.invoke(target, args);
                System.out.println("The methed " + methodName + "end with " + Arrays.asList(args));
                return result;
            }
        };
        proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, handler);
        return proxy;
    }
}
package com.cn.spring.aop.helloworld;

/**
 * Created by jecyhw on 2015/6/20.
 */
public class Main {
    public static void main(String[] args)  {
        ArithmeticCalculator target = new ArithmeticCalculatorImpl();
        ArithmeticCalculator proxy = new ArithmeticCalculatorLoggingProxy(target).getLoggingProxy();

        int result = proxy.add(1, 2);
        System.out.println("-->" + result);

        result = proxy.sub(1, 2);
        System.out.println("-->" + result);

        result = proxy.mul(1, 2);
        System.out.println("-->" + result);

        result = proxy.div(1, 2);
        System.out.println("-->" + result);
    }
}

Spring AOP基础:

  • AOP(Aspect-Oriented Programming 面向切面编程)是一种新的方法论,是对传统OOP(Object-Oriented Programming 面向对象编程)的补充
  • AOP的主要编程对象是切面(aspect),而切面模块化横切关注点
  • 在应用AOP编程时,仍然需要定义公共功能,但可以明确的定义这个功能在哪里,以什么方式应用,并且不必修改受影响的类。这样一来横切关注点就被模块化到特殊的对象(切面)里。
  • AOP的好处:每个事物逻辑位于一个位置,代码不分散,便于维护和升级;业务模块更简洁,只包含核心业务代码。

  • 切面(Aspect):横切关注点(跨越应用程序多个模块的功能)被模块化的特殊对象
  • 通知(Advice):切面必须要完成的工作
  • 目标(Target):被通知的对象
  • 代理(Proxy):向目标对象应用通知之后创建的对象
  • 连接点(Joinpoint):程序执行的某个特定位置:如类某个方法调用前、调用后、方法抛出异常后等,连接点由两个信息确定:方法表示的程序执行点;相对点表示的方位,例如ArithmeticCalculator#add()方法执行前的连接点,执行点为 ArithmeticCalculator#add();方法为该方法执行前的位置
  • 切点(pointcut):每个类都拥有多个连接点:例如ArithmeticCalculator的所有方法实际上都是连接点,即连接点是程序类中客观存在的事物。AOP通过切点定位到特定的连接点。类比:连接点相当于数据库中的记录,切点相当于查询条件。切点和连接点不是一对一的关系,一个切点匹配多个连接点,切点通过org.springframework.aop.Pointcut接口进行描述,它使用类和方法作为连接点的查询条件。
时间: 2024-10-25 21:11:48

15Spring AOP基础的相关文章

CgLib动态代理学习【Spring AOP基础之一】

如果不了解JDK中proxy动态代理机制的可以先查看上篇文章的内容:Java动态代理学习[Spring AOP基础之一] 由于Java动态代理Proxy.newProxyInstance()的时候会发现其参数类型是ClassLoader classLoader, Class<?>[] interface, InvocationHandler handler, 只支持根据接口实现代理类,如果所有代码都是自己掌控,当然没有问题.所有的业务逻辑均抽象出接口,然后所有的业务类实现接口,这样所有的业务类

[Spring框架]Spring AOP基础入门总结二:Spring基于AspectJ的AOP的开发.

前言: 在上一篇中: [Spring框架]Spring AOP基础入门总结一. 中 我们已经知道了一个Spring AOP程序是如何开发的, 在这里呢我们将基于AspectJ来进行AOP 的总结和学习. 一, AspectJ的概述: AspectJ是一个面向切面的框架,它扩展了Java语言.AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件. Spring为了简化自身的AOP的开发,将AspectJ拿过来作为Spring自身一个AOP的开发.

[Spring框架]Spring AOP基础入门总结一.

前言:前面已经有两篇文章讲了Spring IOC/DI 以及 使用xml和注解两种方法开发的案例, 下面就来梳理一下Spring的另一核心AOP. 一, 什么是AOP 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务

AOP基础知识及AOP切面编程之注释方法、xml配置方法

<span style="font-family: 微软雅黑; font-size: 10.5pt; letter-spacing: 0pt; ">AOP概念</span> Aspect(切面):它跟类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是对横切性关注点的抽象 joinpoint(连接点):所谓连接点就是被拦截到的点,在spring中,这些点是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器

spring aop基础概念

spring aop基础概念 1.什么是aop: aspect oriented programming:面向切面编程. 即通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. 主要功能是:日志记录,性能统计,安全控制,事务处理,异常处理等. 2.aop的实现方式: (1)预编译:AspectJ (2)运行期动态代理(JDK动态代理.CGLIB动态代理):SpringAOP.JbossAOP 3.aop的概念: (1)切面(aspect):一个关注点的模块化,这个关注点可能会横切多个

(spring-第16回【AOP基础篇】)基本概念

AOP(Aspect Oriented Programing),面向切面方程.介绍具体定义前,先看一个例子: 1 package com.baobaotao.concept; 2 3 public class ForumService { 4 private TransactionManager transManager; 5 private PerformanceMonitor pmonitor; 6 private TopicDao topicDao; 7 private ForumDao

Spring AOP基础实践

一.代码实践 先上代码,Spring AOP的demo,见下面的小例子. 1 package demo.spring; 2 3 import org.aspectj.lang.annotation.After; 4 import org.aspectj.lang.annotation.Aspect; 5 import org.aspectj.lang.annotation.Before; 6 import org.aspectj.lang.annotation.Pointcut; 7 impor

[Java]Spring AOP基础知识-动态代理

Spring AOP使用动态代理技术在运行期织入增强的代码,为了揭示Spring AOP底层的工作机理,有必要对涉及到的Java知识进行学习.Spring AOP使用了两种代理机制:一种是基于JDK的动态代理:另一种是基于CGLib的动态代理.之所以需要两种代理机制,很大程度上是因为JDK本身只提供接口的代理,而不支持类的代理. 带有横切逻辑的实例 我们通过具体化代码实现上一节所介绍例子的性能监视横切逻辑,并通过动态代理技术对此进行改造.在调用每一个目标类方法时启动方法的性能监视,在目标类方法调

开涛spring3(6.1) - AOP 之 6.1 AOP基础

6.1.1  AOP是什么 考虑这样一个问题:需要对系统中的某些业务做日志记录,比如支付系统中的支付业务需要记录支付相关日志,对于支付系统可能相当复杂,比如可能有自己的支付系统,也可能引入第三方支付平台,面对这样的支付系统该如何解决呢? 传统解决方: 1)日志部分提前公共类LogUtils,定义“longPayBegin”方法用于记录支付开始日志,“logPayEnd”用于记录支付结果: 2)支付部分,定义IPayService接口并定义支付方法“pay”,并定义了两个实现:“PointPayS