这篇文章简单通过一个例子,介绍几种增强的基本配置,以方便spring框架初学者对aop的代码结构有个清楚的了解认识。首先,spring支持aop编程,支持aspectJ的语法格式来表示切入点,切面,增强等,可以两种方式进行配置,一种是基于xml,一种是基于注解,本文介绍基于注解的集中增强的配置和使用。首先,在项目中引入spring的jar包和其他必备的常用jar包,还需引入一个aspectj的支持jar包,maven引用格式为:

		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.7.4</version>
		</dependency>

  版本号自己决定,这样做,可以在JAVA代码中使用如@Aspect注解等,另外,需要在资源配置xml文件中,增加说明:

	<!-- 自动注册service -->
	<context:component-scan base-package="com.minlz.aop.anno" />

	<bean
		class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />

  这样子,就可以自动扫描被注解的aop切面,切入点等。

其他没有介绍的配置选项,参照普通spring项目的环境配置搭建即可,不再啰嗦,下面展示简单的栗子,来说明该如何通过代码和注解配置AOP的组件。

首先是一个主业务逻辑,我们有一个接口和一个实现类,实现类中的方法将传入的参数的绝对值返回,但是如果参数为0,则抛出异常信息。代码如下:

接口:

package com.minlz.aop.anno;
/**
 * @author Bruce.Min
 * @date  2016年7月20日
 */
public interface IAnnoService {

	/**
	 * 主业务
	 * @param param
	 * @return
	 */
	int mainService(int param);
}

实现类为:

package com.minlz.aop.anno;

import org.springframework.stereotype.Component;

/**
 * @author Bruce.Min
 * @date  2016年7月20日
 */
@Component
public class AnnoService implements IAnnoService {

    public int mainService(int param) {
        if(param == 0) {
            throw new RuntimeException("参数为0");
        }
        System.out.println("主业务,参数:" + param);
        return Math.abs(param);
    }

}

然后就是我们的切面实体了:

package com.minlz.aop.anno;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
 * @author Bruce.Min
 * @date  2016年7月20日
 */
@Aspect
@Component
public class AnnoAspectBean {

    /**
     * 切入点声明   * args(param)表明参数,也可以通过增强方法中的JoinPoint获取
     */
    private static final String ASPECT = "execution(* com.minlz.aop.anno.*.*(..)) and args(param)";

    @Before(ASPECT)
    public void before(JoinPoint point, int param) {
        System.out.println("前置通知,参数为:" + param);
    }

    @After(ASPECT)
    public void after(JoinPoint point, int param) {
        System.out.println("后置通知,参数为:" + param);
    }
       /**     * returning 表示主业务的返回值,名称和增强方法中的参数名匹配   */
    @AfterReturning(value = ASPECT, returning = "retValue")
    public void afterReturning(JoinPoint point, int param, int retValue) {
        System.out.println("返回后通知,参数为: " + param + " ,返回值为:" + retValue);
    }

    @AfterThrowing(value = ASPECT, throwing = "ex")
    public void afterThrowing(JoinPoint point, int param, Throwable ex) {
        System.out.println("抛出异常通知,参数为: " + param + ", 异常信息: " + ex.toString());
    }

    @Around(ASPECT)
    public Object around(ProceedingJoinPoint proPoint, int param) throws Throwable {
        System.out.println("环绕通知开始,参数为:" + param);
        Object retValue = proPoint.proceed();
        System.out.println("环绕通知结束,参数为:" + param);
        return retValue;
    }
}

这里,关于切面的实体,有部分需要说明的地方:

1、@Aspect和@Component注解,两个都需要有,前者告之spring这是一个切面,后者告之spring该类被作为组件管理,如果不在资源配置xml中声明该bean且不使用@Component注解,则AOP不会生效。

2、所有的增强方法,都可以传入一个类型为JoinPoint或者ProceddingJoinPoint类型的切入点参数,通过该参数可以获取目标方法和目标方法参数等信息,也可以通过上面代码示例获取方法参数,方法抛出异常和返回值

现在万事俱备,我们写个测试类来测试上面代码的运行结果:

package com.minlz.test.aop;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.minlz.aop.anno.IAnnoService;

/**
 * @author Bruce.Min
 * @date  2016年7月20日
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-aop-anno.xml")
public class AopAnnoTest {

    @Autowired
    private IAnnoService iAnnoService;

    @Test
    public void testAnnoAop() {
        iAnnoService.mainService(-1);     //iAnnoService.mainService(0);
} }

如果参数为-1,则运行结果为:

通过结果可以知道,环绕通知发生在前置通知之前,在后置通知之前的,返回值增强顺序为最后。

如果,把参数改成0,则会抛出异常,那么会有哪些增强还能够继续运行的?结果如下:

可以看到,进入主业务之前,环绕通知前部分和前置通知正常运行,然后主业务抛出异常信息,主业务“完成”,后置通知启动,再接着异常增强运行,但是环绕通知后部分和返回值增强都没有运行!

总结:

 本文只是简单介绍了集中增强的配置和使用,实际使用过程中,可能面临复杂的逻辑,但是原理不变,了解了每种增强的运行时机和结果,综合使用便不是问题。

 PS:如有错误,还请各位赐教,不胜感激!

基于注解的Spring AOP入门、增强Advice实例的更多相关文章

  1. 基于注解的Spring AOP的配置和使用

    摘要: 基于注解的Spring AOP的配置和使用 AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.可以通过预编译方式和运行期动态代理实现在不 ...

  2. 基于注解的Spring AOP示例

    基于注解的Spring AOP示例 目录 在XML配置文件中开启 @AspectJ 支持 声明切面及切入点 声明通知 测试 结语 在XML配置文件中开启 @AspectJ 支持 要使用Spring的A ...

  3. 基于注解的Spring AOP的配置和使用--转载

    AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术. ...

  4. 基于注解的Spring AOP拦截含有泛型的DAO

    出错场景 1.抽象类BaseDao public abstract class BaseDao<T> { public BaseDao() { entityClass = (Class&l ...

  5. (转)使用Spring的注解方式实现AOP入门

    http://blog.csdn.net/yerenyuan_pku/article/details/52865330 首先在Eclipse中新建一个普通的Java Project,名称为spring ...

  6. Spring Aop(二)——基于Aspectj注解的Spring Aop简单实现

    转发地址:https://www.iteye.com/blog/elim-2394762 2 基于Aspectj注解的Spring Aop简单实现 Spring Aop是基于Aop框架Aspectj实 ...

  7. 基于注解的Spring多数据源配置和使用(非事务)

    原文:基于注解的Spring多数据源配置和使用 1.创建DynamicDataSource类,继承AbstractRoutingDataSource package com.rps.dataSourc ...

  8. Spring:基于注解的Spring MVC

    什么是Spring MVC Spring MVC框架是一个MVC框架,通过实现Model-View-Controller模式来很好地将数据.业务与展现进行分离.从这样一个角度来说,Spring MVC ...

  9. Spring笔记07(Spring AOP的通知advice和顾问advisor)

    1.Spring AOP的通知advice 01.接口代码: package cn.pb.dao; public interface UserDao { //主业务 String add(); //主 ...

随机推荐

  1. Mosquitto搭建Android推送服务(三)Mosquitto集群搭建

    文章钢要: 1.进行双服务器搭建 2.进行多服务器搭建 一.Mosquitto的分布式集群部署 如果需要做并发量很大的时候就需要考虑做集群处理,但是我在查找资料的时候发现并不多,所以整理了一下,搭建简 ...

  2. 解决绝对定位div position: absolute 后面的<a> Link不能点击

    今天布局的时候,遇到一个bug,当DIV设置为绝对定位时,这个div后面的相对定位的层里面的<a>Link标签无法点击. 网上的解决方案是在绝对定位层里面添加:pointer-events ...

  3. Linux系统开机默认开启无线网卡

    Linux系统每次重新启动时,不会重新打开无线网卡,需要每次手动去更改. 这里通过两种方式开启无线网卡. 第一种方式就是手动连接到Linux系统,(前提是按照了Linux桌面) 1.找到文件夹为 et ...

  4. 基于Solr的空间搜索

    如果需要对带经纬度的数据进行检索,比如查找当前所在位置附近1000米的酒店,一种简单的方法就是:获取数据库中的所有酒店数据,按经纬度计算距离,返回距离小于1000米的数据. 这种方式在数据量小的时候比 ...

  5. jQuery获取输入框并设置焦点

    $(':input:enabled:visible:first').focus(); $("input:text:visible:first").focus(); 表单元素选择器: ...

  6. [UWP]使用AdaptiveTrigger实现自适应布局

    这篇博客将介绍如何在UWP开发中使用AdaptiveTrigger实现自适应布局. 场景1:窗体宽度大于800时,窗体背景色为绿色,窗体在0到800之间为蓝色. XAML Code: <Grid ...

  7. TDD学习笔记【二】---单元测试简介

    大纲 Testing 的第一个切入点:单元测试. 本篇文章将针对单元测试进行简介,主要内容包含了5W: Why What Where Who When 而How 的部分,属于实现部分,将于下一篇文章介 ...

  8. 清理SYSAUX表空间

    1.查看SYSAUX表空间中数据分布情况 col SEGMENT_NAME for a30 set lines 999 select * from (select segment_name,PARTI ...

  9. UWP Composition API - 锁定列的FlexGrid

    需求是第一列锁定,那么怎么让锁定列不跟着滚动条向做移动呢? 其实很简单,让锁定列跟scrollviewer的滚动做反方向移动. 先看一下这个控件的模板,嗯,其实很简单,就是ListView的模板,不同 ...

  10. Python 学习第十九天 django知识

    一,django 知识总结 1,同一个name属性的标签,多个值获取 <form action="/login/" method="POST" encty ...