Spring AOP

Spring框架的关键组件之一是面向方面编程(AOP)框架。 面向方面的编程需要将程序逻辑分解成不同的部分。

此教程将通过简单实用的方法来学习Spring框架提供的AOP/面向方面编程。

Spring AOP 概述

Spring框架的关键组件之一是面向方面编程(AOP)。 面向方面的编程需要将程序逻辑分解成不同的部分。 跨越应用程序的多个点的功能被称为交叉切割问题,这些交叉关切在概念上与应用程序的业务逻辑分开。有如:日志记录,审计,声明式事务,安全性和缓存等方面的各种常见的的例子。

OOP模块化的关键单位是类,而在AOP中,模块化单位是方面。 依赖注入可帮助您将应用程序对象彼此分离,并且AOP可帮助您将交叉问题与其影响的对象分离。AOP就像Perl.NET,Java等编程语言中的触发器。

Spring AOP模块提供截取拦截应用程序的拦截器,例如,当执行方法时,可以在执行方法之前或之后添加额外的功能。

在开始使用AOP之前,让我们先来熟悉AOP的概念和术语。 这些术语不是Spring特有的,而是与面向方面编程(AOP)有关。

术语描述
方面/切面(Aspect)                                                                                     

一个具有一组API的模块,提供交叉要求。例如,日志记录模块被称为AOP方面用于记录。应用程序可以根据需要具有任意数量的方面。                                                                                              

加入点(Join point)这表示您的应用程序中可以插入AOP方面的一点。也可以说,这是应用程序中使用Spring AOP框架采取操作的实际位置。
通知(Advice)这是在方法执行之前或之后采取的实际操作。 这是在Spring AOP框架的程序执行期间调用的实际代码片段。
切入点(Pointcut)这是一组一个或多个连接点,其中应该执行通知(Advice)。 您可以使用表达式或模式指定切入点,我们将在AOP示例中看到。
介绍(Introduction)介绍允许向现有类添加新的方法或属性。
目标对象(Target object)对象被一个或多个方面通知(Advice),该对象将始终是代理的对象。也称为通知(Advice)对象。
编织(Weaving)编织是将方面与其他应用程序类型或对象进行链接以创建通知(Advice)对象的过程。 这可以在编译时,加载时间或运行时完成。

Spring AOP中可以使用以下五种建议:

通知描述
before在方法执行之前运行通知。
after在方法执行后运行通知,无论其结果如何。
after-returning只有方法成功完成后才能在方法执行后运行通知。
after-throwing只有在方法通过抛出异常而退出方法执行之后才能运行通知。
around在调用通知方法之前和之后运行通知。
<aop:aspectj-autoproxy/>

基于@AspectJ

@AspectJ是指将Java方法注释为Java 5注释的常规Java类的方式。 @AspectJ是指将Java方法注释为Java 5注释的常规Java类的方式。通过在基于XML Schema的配置文件中包含以下元素来启用@AspectJ支持。

声明一个方面(aspect)

方面(aspect)的类就像任何其他正常的bean一样,并且可以像任何其他类一样具有方法和字段,不过它们使用@Aspect进行注释,如下所示:

package org.xyz;

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AspectModule {

}

  
  

它们就像任何其他以XML格式配置的bean一样,如下所示:

<bean id="myAspect" class="org.xyz.AspectModule">
   <!-- configure properties of aspect here as normal -->
</bean>

声明一个切入点

切入点(pointcut)有助于确定要用不同通知执行的关联点(即方法)。 在使用基于@AspectJ的配置时,切入点声明有两部分:

  • 一个切入点表达式,确定哪些方法执行。
  • 切入点签名包括名称和任意数量的参数。 该方法的实体是无关紧要的,也可以是空的。

以下示例定义了一个名为“businessService”的切入点,该切入点将匹配com.xyz.myapp.service包下的类中可用的每个方法的执行:

import org.aspectj.lang.annotation.Pointcut;

@Pointcut("execution(* com.xyz.myapp.service.*.*(..))") // expression 
private void businessService() {}  // signature

  
  

以下示例定义了一个名为“getname”的切入点,该切入点将与com.yiibai包下的Student类中的getName()方法的执行相匹配:

import org.aspectj.lang.annotation.Pointcut;

@Pointcut("execution(* com.yiibai.Student.getName(..))") 
private void getname() {}

声明通知

您可以使用@{ADVICE-NAME}注释在以下所述的五个建议中声明任何一个。假设您已经定义了一个切入点签名方法为businessService(),参考以下配置:

@Before("businessService()")
public void doBeforeTask(){
 ...
}

@After("businessService()")
public void doAfterTask(){
 ...
}

@AfterReturning(pointcut = "businessService()", returning="retVal")
public void doAfterReturnningTask(Object retVal){
  // you can intercept retVal here.
  ...
}

@AfterThrowing(pointcut = "businessService()", throwing="ex")
public void doAfterThrowingTask(Exception ex){
  // you can intercept thrown exception here.
  ...
}

@Around("businessService()")
public void doAroundTask(){
 ...
}

可以为任何通知定义切入点内嵌。 下面是一个为之前通知定义的内联切入点的示例:

@Before("execution(* com.xyz.myapp.service.*.*(..))")
public doBeforeTask(){
 ...
}
  
  

让我们写一个Spring Boot AOP基于注解的应用例子,它将使用基于注解的配置实现通知。打开并使用Eclipse IDE,并按照以下步骤创建一个maven应用程序:

maven pom:

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.6.RELEASE</version>
	</parent>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>

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

Java Bean:

package com.milo.entity;
import java.sql.Timestamp;

import org.springframework.stereotype.Component;

@Component
public class BatchResultBean{
	String id;
	
	String progName="ProgName";
	
	String fileName="fileName";
	
	
	//getting setting....

}


写一个Aspectj 类:

package com.milo.spring.aop;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class Logging {
	
	@Before("execution (* com.milo.entity..*(..))")//指定需要横切的包名或者类名。。。。
	public void logBeforeBean() {
		System.out.println("[beforeAdvice] Going to setup student profile.");
	}
}


在src/main/resources下定义一个application.properties文件:

##自动加载开启spring aop
spring.aop.auto=true



再创建一个Spring Boot Application:

package com.milo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
	
	public static void main(String[] args) {
		SpringApplication.run(App.class, args);
	}
}




接下来编写一个spring boot 测试类:

package com.spring.aop;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.milo.App;
import com.milo.entity.BatchResultBean;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class TestLogging {
	@Autowired
	BatchResultBean bean;
	
	@Before
	public void setUp(){}
	
	@After
	public void tearDown(){}
	
	@Test
	public void testMain(){
		String fileName=this.bean.getFileName();
		System.out.println("FileName:"+fileName);
		String progName=this.bean.getProgName();
		System.out.println("ProgName:"+progName);
	}
}



验证输出结果如下:

[beforeAdvice] Going to setup student profile.
FileName:fileName
[beforeAdvice] Going to setup student profile.
ProgName:ProgName



























摘录于--------《易百教程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OOEM

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值