`
vortexchoo
  • 浏览: 67152 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

Spring AOP 用法笔记

    博客分类:
  • java
阅读更多

最近工作不太忙,把spring aop又重新看了一遍,今天做下笔记,方便以后查看。

 

aop众所周知,是面向切面编程。具体的条条框框概念这里就不说了,百度一大堆。

通俗的来讲就是:对我们期望的一个切点面上的所有地方进行统一的操作。

 

首先需要spring的一些基础的jar包,当然包括aop及其所依赖的jar



 

接着我们需要编写一个类,也就是我例子中的MyAspect

 

 

package org.vic.aop.aspect;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyAspect {
	
	public void printBeginning(){
		System.out.println("hello everyone !");
	}
	
	
	public void printEnd(){
		System.out.println("thank you!");
	}
	
	
	public void printSorry(){
		System.out.println("I'm sorry,I'm too old...");
	}
	
	public void printAround(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("weng weng weng...");
		pjp.proceed();
		System.out.println("weng weng ...");
	}
	
	
}

 

 

这个类是干嘛的呢?

该类其实就是写了aop要做的事情,什么时候做是在aop配置代码中展现的,后面会说。

 

接着是一个service接口及其实现类,里面有一个方法:

 

package org.vic.aop.service;

public interface IMyIntroductionService {
	
	public void doIntroduce(String name,int age);
	
}

 

 

 

package org.vic.aop.service.impl;

import org.vic.aop.service.IMyIntroductionService;

public class MyIntroductionServiceImpl implements IMyIntroductionService {

	@Override
	public void doIntroduce(String name, int age) {
		//if(age>15){
		//	throw new IllegalArgumentException();
		//}
		System.out.println("I'm "+name+" I'm "+age);
	}

}

 

 

    接着写一个controller测试用:

 

package org.vic.aop.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.vic.aop.service.IMyIntroductionService;

@Controller
@RequestMapping("/test")
public class TestController {
	
	private IMyIntroductionService myIntroductionService;
	
	@RequestMapping("/doTest")
	public void doTest(String name,int age){
		myIntroductionService.doIntroduce(name, age);
	}

	public void setMyIntroductionService(
			IMyIntroductionService myIntroductionService) {
		this.myIntroductionService = myIntroductionService;
	}
	
	
}

 

 

代码搞定,接下来开始配置aop:

 

<?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:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
						http://www.springframework.org/schema/mvc 
						http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 
						http://www.springframework.org/schema/context 
						http://www.springframework.org/schema/context/spring-context-3.0.xsd 
						http://www.springframework.org/schema/aop 
						http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
						http://www.springframework.org/schema/tx 
						http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
						http://www.springframework.org/schema/task        
						http://www.springframework.org/schema/task/spring-task-3.0.xsd"
						>

	<!-- 激活spring的注解. -->
	<context:annotation-config />

	<!-- 扫描注解组件并且自动的注入spring beans中. 
	例如,他会扫描@Controller 和@Service下的文件.所以确保此base-package设置正确. -->
	<context:component-scan base-package="org.vic.aop" />

	<!-- 配置注解驱动的Spring MVC Controller 的编程模型.注:次标签只在 Servlet MVC工作! -->
	<mvc:annotation-driven />
	
	<bean id="myIntroductionService" class="org.vic.aop.service.impl.MyIntroductionServiceImpl" />  
	<bean id="myAspect" class="org.vic.aop.aspect.MyAspect"/>
	
	<bean id="testController" class="org.vic.aop.controller.TestController">
		<property name="myIntroductionService" ref="myIntroductionService"/>
	</bean>
	
	<aop:config>  
        <aop:aspect id="aopAspect" ref="myAspect">  
            <!--配置com.spring.service包下所有类或接口的所有方法-->  
            <aop:pointcut id="myPoint"  
                expression="execution(* org.vic.aop.service.*.*(..))" />  
            <aop:before pointcut-ref="myPoint" method="printBeginning"/>  
            <aop:after pointcut-ref="myPoint" method="printEnd"/>  
            <aop:around pointcut-ref="myPoint" method="printAround"/>  
            <aop:after-throwing pointcut-ref="myPoint" method="printSorry" throwing="ex"/>  
        </aop:aspect>  
    </aop:config>  
      
</beans>

 

 

配置aop,首先要配置aspect 也就是 我们的MyAspect类

接着配置poincut,用表达式来说明路径下哪个包下的class文件在执行的时候会被aop影响。

这里我们配置了service包下的class

 

再下来就是重点的了:

before:pointcut-ref="myPoint" 表示当前的before配置是生效于我们的pointcut配置的,凡是service下面的方法被执行时都会先执行我们的before方法对应的method ---> printBeginning

(以上说明对下面的配置同理)

after: 看字面意思也明白了,就是在pointcut中包含的放法执行之后会执行after对应的method---> printEnd

只配置这两项的话打印的内容为:

请求url为:http://127.0.0.1:8080/SpringAOPTest/test/doTest?name=zhangsan&age=11

 

hello everyone !

I'm zhangsan I'm 11

 

thank you!

 

我们看到我们的service实现类的实现方法其实只打印了 I'm zhangsan I'm 11。但由于配置了aop 所以执行了MyAspect中的printBeginning方法(之前),printEnd方法(之后)。

接着配置--------------------------------------------------------------------------

 

around:此配置项对应的method会包围着被调用的service方法执行,优先级(开始优先级)小于begin配置,但结束优先级大于after配置。

 

after-throwing:如果被执行的service方法出现了异常> 放开service方法中的注释

if(age>15){
			throw new IllegalArgumentException();
		}

 如果传入的age>15直接抛出异常。那么如果有异常抛出时就会执行该配置对应的方法。

我们现在将此处代码注释放开,并将aop配置内容全部配置。来看看结果:

 

请求url:http://127.0.0.1:8080/SpringAOPTest/test/doTest?name=zhangsan&age=11

传入age小于15 不会抛出异常,结果:

hello everyone !

weng weng weng...

I'm zhangsan I'm 11

thank you!

 

weng weng ...

以上结果就验证了around配置的特点。一直执行了printEnd方法后(thank you!)后才执行了around对应方法中的最后一句。

 

 

请求url:http://127.0.0.1:8080/SpringAOPTest/test/doTest?name=zhangsan&age=17

本次请求会抛出异常,因为age>15

结果为:

hello everyone !

weng weng weng...

thank you!

I'm sorry,I'm too old...

严重: Servlet.service() for servlet [MVCServlet] in context with path [/SpringAOPTest] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException] with root cause

 

java.lang.IllegalArgumentException....

 

以上结果执行了

after-throwing对应方法中的打印,也就是:I'm sorry,I'm too old...

从结果可以看出:先执行before

接着去执行around

再去执行service方法,但是它抛出异常了,没有执行到打印语句就已经跳出了。

atfer对应的method依然会被执行。

最后执行了我们配置的after-throwing对应的method,之后控制台才打印出来异常信息。

 

附件有测试学习的包,方便快速上手。

 

为了更全面的学习配置,我从别人博客里扒了点东西:

《Spring参考手册》中定义了以下几个AOP的重要概念,结合以上代码分析如下:

  • 切面(Aspect) :官方的抽象定义为“一个关注点的模块化,这个关注点可能会横切多个对象”,在本例中,“切面”就是类TestAspect所关注的具体行为,例如,AServiceImpl.barA()的调用就是切面TestAspect所关注的行为之一。“切面”在ApplicationContext中<aop:aspect>来配置。
  • 连接点(Joinpoint) :程序执行过程中的某一行为,例如,AServiceImpl.barA()的调用或者BServiceImpl.barB(String _msg, int _type)抛出异常等行为。
  • 通知(Advice) :“切面”对于某个“连接点”所产生的动作,例如,TestAspect中对com.spring.service包下所有类的方法进行日志记录的动作就是一个Advice。其中,一个“切面”可以包含多个“Advice”,例如TestAspect
  • 切入点(Pointcut) :匹配连接点的断言,在AOP中通知和一个切入点表达式关联。例如,TestAspect中的所有通知所关注的连接点,都由切入点表达式execution(* com.spring.service.*.*(..))来决定
  • 目标对象(Target Object) :被一个或者多个切面所通知的对象。例如,AServcieImpl和BServiceImpl,当然在实际运行时,Spring AOP采用代理实现,实际AOP操作的是TargetObject的代理对象。
  • AOP代理(AOP Proxy) 在Spring AOP中有两种代理方式,JDK动态代理和CGLIB代理。默认情况下,TargetObject实现了接口时,则采用JDK动态代理,例如,AServiceImpl;反之,采用CGLIB代理,例如,BServiceImpl。强制使用CGLIB代理需要将 <aop:config> 的 proxy-target-class 属性设为true

       通知(Advice)类型

  • 前置通知(Before advice) :在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。ApplicationContext中在<aop:aspect>里面使用<aop:before>元素进行声明。例如,TestAspect中的doBefore方法
  • 后通知(After advice) :当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。ApplicationContext中在<aop:aspect>里面使用<aop:after>元素进行声明。例如,TestAspect中的doAfter方法,所以AOPTest中调用BServiceImpl.barB抛出异常时,doAfter方法仍然执行
  • 返回后通知(After return advice) :在某连接点正常完成后执行的通知,不包括抛出异常的情况。ApplicationContext中在<aop:aspect>里面使用<after-returning>元素进行声明。
  • 环绕通知(Around advice) :包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。ApplicationContext中在<aop:aspect>里面使用<aop:around>元素进行声明。例如,TestAspect中的doAround方法。
  • 抛出异常后通知(After throwing advice) : 在方法抛出异常退出时执行的通知。 ApplicationContext中在<aop:aspect>里面使用<aop:after-throwing>元素进行声明。例如,TestAspect中的doThrowing方法。

       切入点表达式

  • 通常情况下,表达式中使用”execution“就可以满足大部分的要求。表达式格式如下:
  • 大小: 150.9 KB
分享到:
评论

相关推荐

    spring aop 学习笔记

    本学习笔记将深入探讨Spring AOP的核心概念、工作原理以及实际应用。 1. **核心概念** - **切面(Aspect)**:切面是关注点的模块化,包含业务逻辑之外的横切关注点,如日志、事务管理。 - **连接点(Join Point...

    Spring AOP IOC源码笔记.pdf

    Spring AOP基于代理实现,可以使用接口代理(JDK动态代理)或类代理(CGLIB)。 7. CGLIB: CGLIB是Spring AOP默认的代理库,用于生成目标类的子类,从而实现方法拦截。当目标类没有实现接口时,Spring会使用CGLIB...

    SpringAop学习笔记以及实现Demo

    **Spring AOP 学习笔记及实现Demo** Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架中的一个重要组成部分,它提供了一种在不修改源代码的情况下,对程序进行功能增强的技术。AOP的主要目的...

    spring源码--AOP流程--笔记.docx

    Spring AOP 源码分析笔记 Spring AOP(Aspect-Oriented Programming)是一种编程范式,它允许开发者 modularize cross-cutting concerns,即将横切关注点模块化。AOP 使得开发者可以将一些公共的功能模块化,以便在...

    Spring AOP 使用笔记

    本笔记主要探讨了如何在Spring应用中使用AOP来实现横切关注点,如日志、事务管理、性能监控等。 首先,理解AOP的基本概念至关重要。AOP的核心是切面(Aspect),它封装了跨越多个对象的行为或责任。切面由两个主要...

    Spring AOP源码笔记

    【Spring AOP源码笔记】 Spring AOP是Spring框架的核心组件之一,它实现了面向切面编程(Aspect-Oriented Programming,简称AOP),允许开发者定义“切面”,这些切面可以封装横切关注点,如日志记录、事务管理等。...

    Spring AOP 复习笔记.rar

    Spring AOP还支持使用AspectJ的强大的表达式语言来声明切入点。AspectJ提供了更全面的面向切面编程功能,包括类型的匹配、编译时织入等。在Spring中,可以通过以下方式启用AspectJ支持: ```xml &lt;aop:aspectj-...

    ssh-aop笔记

    SSH-AOP笔记主要涵盖的是Spring、Struts和Hibernate三大框架集成使用时,如何结合Aspect Oriented Programming(面向切面编程)的理念进行应用增强。在Java企业级开发中,SSH是常用的MVC架构,而AOP则是一种编程范式...

    spring ioc aop mvc boot-学习笔记.docx

    Spring框架是Java开发中不可或缺的一部分,它为开发者提供了强大的依赖注入(IOC)和面向切面编程(AOP)功能,以及用于构建Web应用程序的MVC框架。Spring Boot则是基于Spring框架构建的应用程序启动器,旨在简化...

    Spring_AOP笔记Spring_AOP笔记

    在实际开发中,Spring AOP的使用不仅可以提高代码质量,还能帮助开发者专注于业务逻辑,而不是被琐碎的服务细节所困扰。因此,理解和掌握Spring AOP对于任何Java开发者来说都是一项重要的技能。

    拿捏面试官-Spring AOP IOC源码笔记

    - **cglib代理**:Spring AOP使用动态代理技术,如JDK动态代理和CGLIB,实现切面编程。 - **手动实现AOP**:编写切面类,定义通知方法。 - **AOP的概述**:AOP用于封装横切关注点,如日志、事务、性能监控等。 -...

    Spring IOC和AOP代码与笔记整理

    5. **代理(Proxy)**:Spring AOP通过JDK动态代理或CGLIB代理来创建一个目标对象的代理,以便在调用目标方法时插入通知。 实际操作中,我们可以使用注解来声明切面,例如`@Aspect`、`@Before`、`@After`等,也可以...

    Spring全家桶知识笔记.pdf

    使用注解是一种简洁的方法,Spring提供了大量注解来简化开发,如@Autowired、@Component、@Service等。 Spring全家桶包含的核心组件众多,如Spring Core Container(包括Bean Factory和Context模块)、Spring MVC、...

    Spring相关的笔记,包含ioc、DI、AOP、Spring事务等等

    5. **Spring笔记**:这份笔记很可能详细记录了如何配置Spring容器,如何编写bean定义,如何实现DI,创建和使用AOP切面,以及如何配置和管理事务。此外,还可能涵盖了Spring Boot、Spring MVC、Spring Data JPA等相关...

    spring-note spring 读书笔记

    `spring_ioc.txt`可能详细解释了如何定义Bean、Bean的初始化和销毁方法,以及如何通过XML和Java配置实现IOC。 2. **面向切面编程(AOP)**: AOP允许在不修改业务代码的情况下,实现如日志记录、性能监控等横切关注...

    Spring学习笔记(精华全记录)

    ### Spring学习笔记(精华全记录) #### Spring框架概述 Spring框架源自Rod Johnson的个人项目,最初于2002年末发布。Spring并非一开始就作为一个完整的框架出现,而是从一个项目逐步发展而来。随着项目的成熟,...

    Spring学习笔记&源码

    Spring框架是Java开发中不可或缺的一部分,它以其IoC(控制反转)和AOP(面向切面编程)的核心特性,极大地简化了企业级应用的开发。本资料“Spring学习笔记&源码”是基于网易云课堂黑马程序员的Spring四天精通课程...

    马士兵Spring课堂笔记(超级详细版).pdf

    马士兵Spring课堂笔记(超级详细版) 本资源主要讲解了Spring框架的基础概念和应用,涵盖了面向接口编程、IOC/DI、AOP、Spring应用IOC/DI、Spring应用AOP、Struts2.1.6 + Spring2.5.6 + Hibernate3.3.2整合、Spring...

Global site tag (gtag.js) - Google Analytics