`

Spring AOP 使用笔记

阅读更多

先搬上一位大神写的spring aop 实现原理,概念性的东西也比较全。(后面是我写的例子)

其实关于aop的东西之前也看过好多遍了,但是概念性的东西也容易混淆,工作中写的概率也很低,以上其实可以理解为不会了

所以今天抽时间写了个例子来巩固下,顺带搬点概念,整理下来,以便之后复习思路更清晰,开始吧!

 

什么是AOP

AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需 要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日 志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种 散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

而AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为 “Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低 模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为; 那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手 将这些剖开的切面复原,不留痕迹。

使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横 切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。正如Avanade公司的高级方案构架师Adam Magee所说,AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”

实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

 

AOP使用场景

AOP用来封装横切关注点,具体可以在下面的场景中使用:

 

Authentication 权限

Caching 缓存

Context passing 内容传递

Error handling 错误处理

Lazy loading 懒加载

Debugging  调试

logging, tracing, profiling and monitoring 记录跟踪 优化 校准

Performance optimization 性能优化

Persistence  持久化

Resource pooling 资源池

Synchronization 同步

Transactions 事务

 

AOP相关概念

 

方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的 Advisor或拦截器实现。

 

连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用或特定的异常被抛出。

 

通知(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多 AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice

 

切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上

 

引入(Introduction): 添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来 配置Advice和代理类要实现的接口

 

目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。POJO

 

AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

 

织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。

 

AOP示例

 

注解方式实现:

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.quainter</groupId>
	<artifactId>base</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>quainter-test</name>
	<url>http://maven.apache.org</url>

	<properties>
		<spring.version>4.2.5.RELEASE</spring.version>
		<aspectj.version>1.8.9</aspectj.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${aspectj.version}</version>
		</dependency>

		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>${aspectj.version}</version>
		</dependency>

	</dependencies>
</project>

 

<?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:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context-4.2.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
	
	<context:component-scan base-package="org.quainter.aop" />
	<aop:aspectj-autoproxy />
	
</beans>

 

package org.quainter.aop.advice;

import org.springframework.stereotype.Component;

@Component
public class TestService {

	public void testMethod(String message) {
		System.out.println("i am the service method..");
		System.out.println("Message:   " + message);
	}

}

 

package org.quainter.aop.advice;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
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.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class TestAdvice {

	@Pointcut("execution(* *.testMethod(..))")
	public void test() {
	}

	@Before("test()")
	public void beforeTest() {
		System.out.println("beforeTest...");
	}

	@After("test()")
	public void afterTest() {
		System.out.println("afterTest...");
	}

	@Around("test()")
	public void aroundTest(ProceedingJoinPoint p) {

		System.out.println("startMethod...");
		try {
			p.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("endMethod...");

	}

	@AfterThrowing("test()")
	public void throwTest() {
		System.out.println("occured an exception...");
	}

}

 

package org.quainter.aop.advice;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTest {

	public static void main(String[] args) {
		ApplicationContext af = new ClassPathXmlApplicationContext(
				"spring/applicationContext-aop-annotation.xml");
		System.out.println(af.getBean("testAdvice"));
		TestService ts = (TestService) af.getBean("testService");
		ts.testMethod("hello aspectj");
	}

}

 

org.quainter.aop.advice.TestAdvice@42b5548
startMethod...
beforeTest...
i am the service method..
Message:   hello aspectj
endMethod...
afterTest...

需要注意的地方:

 

1、使用@Component将类加载到spring容器中

2、配置了<context:component-scan>之后<context:annotation-config/>标签就可以不再配置了

 

配置方式实现:

<?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:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
	
	<bean id="testService" class="org.quainter.aop.advice.TestService" />    
	<bean id="testAdvice" class="org.quainter.aop.advice.TestAdvice" />    
      
    <aop:config>
        <aop:aspect ref="testAdvice">    
            <aop:pointcut id="testPoint" expression="execution(* *.testMethod(..))" />    
            <aop:before pointcut-ref="testPoint" method="beforeTest"/>    
            <aop:after pointcut-ref="testPoint" method="afterTest"/>    
            <aop:around pointcut-ref="testPoint" method="aroundTest"/>    
            <aop:after-throwing pointcut-ref="testPoint" method="throwTest" throwing="ex"/>    
        </aop:aspect>    
    </aop:config> 
	
</beans>

上面java文件里的注解全部去掉

MainTest里面加载另外一个配置文件,对应代码

ApplicationContext af = new ClassPathXmlApplicationContext(
				"spring/applicationContext-aop-config.xml");

运行,运行结果同上。

 

OK,记录防忘吐舌头

 

 

分享到:
评论

相关推荐

    spring aop 学习笔记

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

    SpringAop学习笔记以及实现Demo

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

    Spring AOP学习笔记

    NULL 博文链接:https://linres.iteye.com/blog/281221

    Spring Aop 学习笔记

    Spring Aop 学习笔记

    Spring AOP IOC源码笔记.pdf

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

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

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

    Spring AOP源码笔记

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

    Spring AOP 复习笔记.rar

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

    Spring AOP 用法笔记

    1. **注解驱动的AOP**:在Spring 2.5引入了基于注解的AOP,允许我们在切面类和方法上直接使用`@Aspect`、`@Before`、`@After`等注解,简化了配置。 2. **XML配置的AOP**:在Spring的XML配置文件中定义切面、通知、...

    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开发者来说都是一项重要的技能。

    SpringAOP案例代码笔记

    Spring的AOP开发(XML)Spring的AOP的注解开发 代码案例

    JAVA Spring AOP面向切面编程笔记

    JAVA Spring AOP面向切面编程笔记

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

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

    马士兵老师spring框架学习笔记

    这份笔记涵盖了Spring的核心概念、配置、AOP(面向切面编程)、DI(依赖注入)等关键知识点。 1. **Spring框架概述**:Spring是一个开源的Java平台,提供了一个全面的编程和配置模型,支持构建更简洁、更易于测试和...

    Spring框架学习笔记

    Spring框架是Java开发中广泛应用的轻量级框架,它以其依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)为核心特性,极大地简化了企业级应用的开发工作。这份"Spring框架...

Global site tag (gtag.js) - Google Analytics