结合代码彻底理解Spring AOP的术语

原创 2017年05月16日 14:54:29

每本Spring的书在介绍AOP之前,总能有一箩筐的术语,看半天似懂非懂,也就没兴趣再继续学习下去,其实并没有这么复杂。

难懂的定义我们就不贴了,就说说咱们通俗的解释,下面让我们结合代码来理清楚各个术语的含义

一、Advice(通知,叫增强更贴切低啊,也更好理解)

增强可以这么理解:为某些方法增加某些功能,这些功能可以安全、事物、日志等;

增强分为前置增强(Before Advice):对方法执行前进行的增强

                后置增强(After Advice):对方法执行后进行的增强

                环绕增强(Around Advice):可以理解为前置增强跟后置增强的合体

                抛出增强(Throw Advice):方法抛出异常后退出执行的增强

                引入增强(Introduction Advice):动态的让被增强的类实现一个接口

代码伺候:

先看前置增强、后置增强以及环绕增强,下面是jdk动态代理的代理类

package com.bckj.proxy.jdk;

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


public class Invo implements InvocationHandler {
    private Object target;

    public Invo(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object o, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(target, args);
        after();
        return result;
    }
    
    private void before(){
        System.out.println("------method start------");
    }
    private void after(){
        System.out.println("------method end------");
    }
    
}
上面例子中的invoke方法中before方法就叫前置加强,像after这样的方法就叫后置加强,before跟after兼具就叫环绕加强,下面看Spring Aop的代码

接口:

package test;

/**
 * Created by DoodleJump on 2017/5/16.
 */
public interface Greeting {
    void sayHello(String name);
}

实现类:

package test;

import org.springframework.stereotype.Component;

/**
 * Created by DoodleJump on 2017/5/16.
 */
@Component
public class GreetingImpl implements Greeting {
    @Override
    public void sayHello(String name) {
        System.out.println("Hello! "+name);
    }
}
前置增强类(实现org.springframework.aop.MethodBeforeAdvice接口):

package test;

import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
 * 前置增强
 */
@Component
public class GreetingBeforeAdvice implements MethodBeforeAdvice{

    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println(method.getName()+" start!");
    }
}
后置增强类(实现org.springframework.aop.AfterReturningAdvice接口):

package test;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
 * 后置增强
 */
@Component
public class GreetingAfterAdvice implements AfterReturningAdvice {

    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println(method.getName()+" end!");
    }
}
环绕增强类(实现org.aopalliance.intercept.MethodInterceptor接口):

package test;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.stereotype.Component;
/**
 * 环绕增强
 */
@Component
public class GreetingAroundAdvice implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        before(methodInvocation);
        Object result = methodInvocation.proceed();
        after(methodInvocation);
        return result;
    }

    private void before(MethodInvocation methodInvocation){
        System.out.println(methodInvocation.getMethod().getName()+" start!");
    }

    private void after(MethodInvocation methodInvocation){
        System.out.println(methodInvocation.getMethod().getName()+" end!");
    }
}
就以环绕增强类为例,spring配置文件的配置如下

<context:component-scan base-package="test" />

     <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
          <!--需要代理的接口-->
          <property name="proxyInterfaces" value="test.Greeting"/>
          <!--接口实现类-->
          <property name="target" ref="greetingImpl"/>
          <!--拦截器名称(也就是增强类名称)-->
          <property name="interceptorNames">
               <list>
                    <value>greetingAroundAdvice</value>
               </list>
          </property>
     </bean>
测试类:

package test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * Created by DoodleJump on 2017/5/16.
 */
public class Client {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring/ApplicationContext.xml");
        Greeting greeting = (Greeting)context.getBean("greetingProxy");
        greeting.sayHello("Jack");
    }
}
测试结果:



下面来看抛出增强:

抛出增强类(实现org.springframe.aop.ThrowAdvice接口,该接口仅仅为标识接口,没有抽象方法,但是实现类必须得有afterThrowing这个方法,不然spring在反射的时候会抛出java.lang.IllegalArgumentException: At least one handler method must be found in class [class test.GreetingThrowAdvice] 这个异常)

package test;

import org.springframework.aop.ThrowsAdvice;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
 * Created by DoodleJump on 2017/5/16.
 */
@Component
public class GreetingThrowAdvice implements ThrowsAdvice {

    public void afterThrowing(Method method,Object[] args,Object target,Exception e){
        System.out.println("----------Throw Exception----------");
        System.out.println("Target Class: "+target.getClass().getName());
        System.out.println("Method Name: "+method.getName());
        System.out.println("Exception Message: "+e.getMessage());
        System.out.println("-----------------------------------");
    }
}
让实现类的方法抛出一个异常:

@Component
public class GreetingImpl implements Greeting {
    @Override
    public void sayHello(String name) {
        System.out.println("Hello! "+name);
        throw new RuntimeException("Error");
    }
}
配置文件的话就把增强类名称改为greetingThrowAdvice,测试类不变,测试结果:



引入增强:

动态实现的接口:

package test;

/**
 * Created by DoodleJump on 2017/5/16.
 */
public interface Apology {
    void saySorry(String name);
}
引入增强类(继承org.springframework.aop.support.DelegationIntroductionInterceptor并实现动态接口):

package test;

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
import org.springframework.stereotype.Component;

/**
 * Created by DoodleJump on 2017/5/16.
 */
@Component
public class GreetingIntroAdvice extends DelegatingIntroductionInterceptor implements Apology {
    @Override
    public void saySorry(String name) {
        System.out.println("Sorry! "+name);
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        return super.invoke(invocation);
    }
}
spring配置文件:

<bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
          <!--需要代理的接口-->
          <property name="proxyInterfaces" value="test.Apology"/>
          <!--接口实现类-->
          <property name="target" ref="greetingImpl"/>
          <!--拦截器名称(也就是增强类名称)-->
          <property name="interceptorNames">
               <list>
                    <value>greetingIntroAdvice</value>
               </list>
          </property>
          <!--代理目标类(false:jdk代理,true:cglib代理)-->
          <property name="proxyTargetClass" value="true"/>
     </bean>
测试类:

package test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * Created by DoodleJump on 2017/5/16.
 */
public class Client {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring/ApplicationContext.xml");
        GreetingImpl greetingImpl = (GreetingImpl)context.getBean("greetingProxy");
        greetingImpl.sayHello("Jack");
        Apology apology = (Apology) greetingImpl;
        apology.saySorry("Jack");
    }
}
测试结果:

可以看到生成的代理类动态的实现了Apology这个接口。

二、Weaving(织入):对方法的增强,比如上面所说的前置增强、后置增强以及环绕增强都是织入的表现

根据不同的实现技术,AOP有三种织入的方式:
    a、编译期织入,这要求使用特殊的Java编译器。
    b、类装载期织入,这要求使用特殊的类装载器。
    c、动态代理织入,在运行期为目标类添加增强生成子类的方式。
    Spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。

三、Introduction(引入):对类的增强,比如上面所说的引入增强


四、Pointcut(切):切入的连接点,即织入或引入发生的那个方法或类


五、Aspect(切面):增强+切点,配置如下



六、Join Point(连接点):所有可以切入的点,切点只是你选择的部分连接点












Spring AOP概念理解 (通俗易懂)

源地址:http://www.verydemo.com/demo_c143_i20837.html 1.我所知道的aop   初看aop,上来就是一大堆术语,而且还有个拉风的名字,面向切面编程,都...
  • qukaiwei
  • qukaiwei
  • 2015-12-21 00:50:07
  • 17254

Spring的AOP框架的主要术语

代理(Proxy)是由AOP框架生成的一个对象,用来
  • lms1719
  • lms1719
  • 2014-05-18 00:08:53
  • 1251

谈谈对AOP的认识二——AOP概念术语理解

一、AOP的术语         上篇博客介绍了AOP的由来,及使用aop的便利,在深入了解aop之前,我们当然得先了解一下其众多的概念性术语:         1、 切面(Aspect) ...
  • wangyongxia921
  • wangyongxia921
  • 2015-06-24 22:18:12
  • 2417

Spring中AOP操作的相关术语

Joinpoint(连接点): 类里面可以被增强的方法,这些方法称为连接点   Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义.   Advice(通...
  • qq_24693837
  • qq_24693837
  • 2017-02-07 15:00:55
  • 625

Spring AOP 术语解释

转自: 1.我所知道的aop    初看aop,上来就是一大堆术语,而且还有个拉风的名字,面向切面编程,都说是OOP的一种有益补充等等。一下子让你不知所措,心想着:怪不得很多人都和我说aop多...
  • yuanye348623610
  • yuanye348623610
  • 2013-04-19 12:55:10
  • 1633

Spring AOP 学习的好例子 仔细理解一定能学会的!

第一次写博客!心情还是蛮激动的! 虽然水品一般!但是我是知识的传播者!希望能把好的文章分享给大家!       好了,言归正传,开始我们的  spring aop 的开心学习之旅吧!      本文转...
  • u011225629
  • u011225629
  • 2015-04-22 11:11:57
  • 5601

Spring AOP的实现——对AOP的理解

什么是AOP AOP(Aspect Orient Programming,即面向切面编程)。AOP和OOP(Object Orient Programming,面向对象编程)互为补充,面向对象编程将...
  • bingogirl
  • bingogirl
  • 2016-08-17 00:55:15
  • 2078

AOP术语详解

==== 关注点 (Concern)====  关注点就是我们要考察或解决的问题。如订单的处理,用户的验证、用户日志记录等都属于关注点。   关注点中的核心关注点 (Core Concerns)...
  • zhangJIAwei520
  • zhangJIAwei520
  • 2012-04-18 19:41:43
  • 2510

Spring的aop名词解释

public class UserServiceImpl implements UserService { @Override public void save() { System.out.pr...
  • lyfls
  • lyfls
  • 2017-06-21 07:47:03
  • 294

Spring AOP之动态代理原理解析

首先声明,这篇文是看马士兵老师的Spring动态代理视频后写出来的。我是初学者,欢迎指正! 本示例模拟的是为一个接口的实现类的每个方法执行前和执行后各加一个日志。 首先,第一步,通用接口 packag...
  • menggudaoke
  • menggudaoke
  • 2015-07-12 23:01:04
  • 2000
收藏助手
不良信息举报
您举报文章:结合代码彻底理解Spring AOP的术语
举报原因:
原因补充:

(最多只允许输入30个字)