SpringAOP基础以及四种实现方式
首先。AOP 面向切面编程。
就是说通过配置将业务逻辑和系统的服务分离。目的是让业务逻辑之关系业务的处理而不再去处理其他事情。其中切面一般都是哪些可以为多个类提供服务的模块,将其封装起来称为切面。减少系统的重复代码和低模块之间的耦合度。一般用于权限验证、日志、事务等。
拦截器也是应用了AOP的思想,将拦截(请求)Action以进行一些预处理或者结果处理。Spring的AOP可以拦截Spring管理的bean。
AOP主要是通过动态代理和反射机制实现的。
Spring代理实际上是对JDK代理和CGLIB代理做了一层封装,并且引入了AOP概念:Aspect、advice、joinpoint等等,同时引入了AspectJ中的一些注解@pointCut,@after,@before等等.Spring Aop严格的来说都是动态代理,所以实际上Spring代理和Aspectj的关系并不大.
基础概念
- 通知(Advice)
定义了切入点代码执行时间点附近需要做的工作。
切入点:
@Before org.apringframework.aop.MethodBeforeAdvice
@After-returning(返回后) org.springframework.aop.AfterReturningAdvice
@After-throwing(抛出后) org.springframework.aop.ThrowsAdvice
@Arround周围 org.aopaliance.intercept.MethodInterceptor
@Introduction引入 org.springframework.aop.IntroductionInterceptor
2. 连接点(Joinpoint)
程序能够应用通知的一个时机。这些时机就是连接点。比如方法调用时、异常抛出时、方法返回后等。
3. 切入点(Pointcut)
通知定义了切面要发生的故事,连接点定义了故事要发生的时机,而切入点定义了故事发生的地点,例如某个类or方法的名称。Spring中允许我们用正则表达式来指定。
- 切面(Aspect)
Advice Joinpoint Pointcut共同组成了切面:要发生的故事、时间、地点 - 引入(Introduction)
引入允许我们向现有的类添加新的方法和属性。
Spring中的方法注入的功能。 - 目标(Target)
就是被通知的对象。
如果没有AOP,通知的逻辑就要写在目标对象中。有了AOP之后他可以只关注自己要做的事情,解耦。 - 代理(Proxy)
应用通知的对象。 - 织入(Weaving)
把切面应用到目标对象来创建新的代理对象的过程。
织入一般发生在以下几个时机:
一 编译时:AspectJ的织入编译器
二 类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码。
三 运行时 :切面在运行的某一个时刻被织入,SpringAOP就是运行时织入切面的。(JDK的动态代理技术)
使用AOP的几种方式:
- 经典的基于代理的AOP
- @AspectJ注解驱动的切面
- 纯POJO切面
- 注入式AspectJ切面
举一个例子:
Me类是实现了Sleepable的接口,重写了其中的sleep方法。
基于代理的AOP
- 由于Me完成了sleep的逻辑,但是其他睡觉需要的功能 ,例如起床穿衣服,睡前脱衣服都可以由AOP代替“Me”执行。实现解耦。
那么我们就可以通过SleepHelper类
public class SleepHelper implements MethodBeforeAdvice, AfterReturningAdvice { public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable { System.out.println("睡觉前要脱衣服!"); } public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable { System.out.println("起床后要穿衣服!"); } }
- Spring配置文件 application.xml配置AOP
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
<span style="white-space:pre"> </span>xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<span style="white-space:pre"> </span>xmlns:aop="http://www.springframework.org/schema/aop"
<span style="white-space:pre"> </span>xsi:schemaLocation="http://www.springframework.org/schema/beans
<span style="white-space:pre"> </span>http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
<span style="white-space:pre"> </span>http://www.springframework.org/schema/aop
<span style="white-space:pre"> </span>http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <!-- 定义被代理者 --> <bean id="me" class="com.springAOP.bean.Me"></bean> <!-- 定义通知内容,也就是切入点执行前后需要做的事情 --> <bean id="sleepHelper" class="com.springAOP.bean.SleepHelper"></bean> <!-- 定义切入点位置 --> <bean id="sleepPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut"> <property name="pattern" value=".*sleep"></property> </bean> <!-- 使切入点与通知相关联,完成切面配置 --> <bean id="sleepHelperAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="advice" ref="sleepHelper"></property> <property name="pointcut" ref="sleepPointcut"></property> </bean> <!-- 设置代理 --> <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 代理的对象,有睡觉能力 --> <property name="target" ref="me"></property> <!-- 使用切面 --> <property name="interceptorNames" value="sleepHelperAdvisor"></property> <!-- 代理接口,睡觉接口 --> <property name="proxyInterfaces" value="com.springAOP.bean.Sleepable"></property> </bean> </beans>
其中配置标签中的几个重要属性
xmlns:是默认的xml文档解析格式,即spring的beans。地址是http://www.springframework.org/schema/beans;通过设置这个属性,所有在beans里面声明的属性,可以直接通过<>来使用,比如<bean>等等。一个XML文件,只能声明一个默认的语义解析的规范。例如上面的xml中就只有beans一个是默认的,其他的都需要通过特定的标签来使用,比如aop,它自己有很多的属性,如果要使用,前面就必须加上aop:xxx才可以。类似的,如果默认的xmlns配置的是aop相关的语义解析规范,那么在xml中就可以直接写config这种标签了。xmlns:xsi:是xml需要遵守的规范,通过URL可以看到,是w3的统一规范,后面通过xsi:schemaLocation来定位所有的解析文件。xmlns:aop:这个是重点,是我们这里需要使用到的一些语义规范,与面向切面AOP相关。xmlns:tx:Spring中与事务相关的配置内容。
- 测试:通过AOP代理的方式执行Me的sleep()方法,会把执行前、执行后的操作执行,实现了AOP的效果!
public class Test { public static void main(String[] args){ @SuppressWarnings("resource") //如果是web项目,则使用注释的代码加载配置文件,这里是一般的Java项目,所以使用下面的方式 //ApplicationContext appCtx = new ClassPathXmlApplicationContext("application.xml"); ApplicationContext appCtx = new FileSystemXmlApplicationContext("application.xml"); Sleepable me = (Sleepable)appCtx.getBean("proxy"); me.sleep(); }
}
然后我们其实可以通org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator简化配置。
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
在Test中就可以直接获取me对象,执行sleep方法。自动匹配,切面会自动匹配符合切入点的bean,会被自动代理,实现功能。
AspectJ提供的注解实现AOP
AspactJ框架常用注解:
@PonitCut // 声明切入点的注解
@Before // 声明前置通知注解
@After // 声明后置通知注解(原始方法执行正常或者非正常执行都会进入)
@AfterReturing //声明后置通知注解(原始方法必须正常执行)
@AfterThrowing // 声明异常通知
@Around // 环绕通知注解
- 修改SleepHelper类
@Aspect
public class SleepHelper{ public SleepHelper(){ } @Pointcut("execution(* *.sleep())") public void sleeppoint(){} @Before("sleeppoint()") public void beforeSleep(){ System.out.println("睡觉前要脱衣服!"); } @AfterReturning("sleeppoint()") public void afterSleep(){ System.out.println("睡醒了要穿衣服!"); } }
在方法中,可以加上JoinPoint参数以进行相关操作,如:
//当抛出异常时被调用
public void doThrowing(JoinPoint point, Throwable ex)
{
System.out.println(“doThrowing::method "
+ point.getTarget().getClass().getName() + “.”
+ point.getSignature().getName() + " throw exception”);
System.out.println(ex.getMessage());
}然后修改配置为:
<aop:aspectj-autoproxy />
<!-- 定义通知内容,也就是切入点执行前后需要做的事情 -->
<bean id="sleepHelper" class="com.springAOP.bean.SleepHelper"></bean>
<!-- 定义被代理者 -->
<bean id="me" class="com.springAOP.bean.Me"></bean>
测试
public class Test {
public static void main(String[] args){
@SuppressWarnings(“resource”)
//如果是web项目,则使用注释的代码加载配置文件,这里是一般的Java项目,所以使用下面的方式
//ApplicationContext appCtx = new ClassPathXmlApplicationContext(“application.xml”);
ApplicationContext appCtx = new FileSystemXmlApplicationContext(“application.xml”);
Sleepable me = (Sleepable)appCtx.getBean(“me”);
me.sleep();
}
}
Pojo切面
使用Spring来定义纯粹的POJO切面
(名字很绕口,其实就是纯粹通过aop:fonfig标签配置,也是一种比较简单的方式)。
修改SleepHelper类,所以这种方式的优点就是在代码中不体现任何AOP相关配置,纯粹使用xml配置。
public class SleepHelper{
public void beforeSleep(){ System.out.println("睡觉前要脱衣服!"); } public void afterSleep(){ System.out.println("睡醒了要穿衣服!"); }
}
配置文件
<?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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <!-- 定义通知内容,也就是切入点执行前后需要做的事情 --> <bean id="sleepHelper" class="com.springAOP.bean.SleepHelper"></bean> <!-- 定义被代理者 --> <bean id="me" class="com.springAOP.bean.Me"></bean> <aop:config> <aop:aspect ref="sleepHelper"> <aop:before method="beforeSleep" pointcut="execution(* *.sleep(..))" /> <aop:after method="afterSleep" pointcut="execution(* *.sleep(..))" /> </aop:aspect> </aop:config> </beans>
- 另一种配置写法
<aop:config> <aop:aspect ref="sleepHelper"> <aop:pointcut id="sleepHelpers" expression="execution(* *.sleep(..))" /> <aop:before pointcut-ref="sleepHelpers" method="beforeSleep" /> <aop:after pointcut-ref="sleepHelpers" method="afterSleep" /> </aop:aspect>
</aop:config>
转自:https://blog.csdn.net/summer_yuxia/article/details/75104949
SpringAOP基础以及四种实现方式相关推荐
- 【Python基础】Python爬虫的两套解析方法和四种信息提取方式
Python爬虫 Author:Iouwill Machine Learning Lab 分享一篇往日旧文章,非常实用. 对于大多数朋友而言,爬虫绝对是学习python的最好的起手和入门方式.因为爬虫 ...
- P21-前端基础-CSS颜色四种表示方式
P21-前端基础-CSS颜色四种表示方式 1.概述 颜色单位: 在CSS中可以直接使用颜色名来设置各种颜色 比如:red.orange.yellow.blue.green - - 但是在css中直接使 ...
- Android开发之入门基础篇--拨号器的四种实现方式
整理之前的学习笔记,发现了很多在学习Android基础的过程中的一些很适合一些新手开发的代码,想想之前也是一步一个脚印,一行一行的代码敲出来的,虽然这些代码很简单,但是里面的编程思路却是很有学习意义的 ...
- Java基础14 集合(重要)四种遍历方式 list 并发异常 set
一.collection 带all的方法 package day14;import java.util.ArrayList; import java.util.Collection;public cl ...
- Android开发的之基本控件和详解四种布局方式
Android中的控件的使用方式和iOS中控件的使用方式基本相同,都是事件驱动.给控件添加事件也有接口回调和委托代理的方式.今天这篇博客就总结一下Android中常用的基本控件以及布局方式.说到布局方 ...
- Java的四种引用方式
Java的四种引用方式 java内存管理分为内存分配和内存回收,都不需要程序员负责,垃圾回收的机制主要是看对象是否有引用指向该对象. java对象的引用包括 强引用,软引用,弱引用,虚引用 Jav ...
- 连续分配存储的四种管理方式
连续分配存储的四种管理方式 连续分配方式指为一个用户程序分配给一个连续的内存空间 单一连续分配 原理:将内存分为用户区和系统区,每次运行时,都将整个用户区分配给当前执行的一道作业 固定分区分配 原理: ...
- 华人科学家发现第四种传热方式!真空声子传热将改写物理教科书
早在上中学时,我们就知道传热一共有三种方式,热传导.热对流.热辐射.如今,这一教科书上的知识要被改写了. 近期,一篇发表在<自然>杂志上的论文让不少传热学.物理学.量子力学等领域的科学家们 ...
- hfc网络文件服务器,网络、LAN、HFC、PLC四种接入方式的总结_网络_LAN_HFC_课课家...
现在几乎每家每户应该都通了宽带,目前,家庭用户的宽带接入主要有ADSL.LAN.HFC.四种方式可以实现,而由于拥有网络的限制,任何一家宽带接入服务商为用户提供的接入方式只能是其中的一种或两种.现在互 ...
- HashMap遍历的四种常用方式
古人云:温故而知新. 最近闲来无事就去翻阅了一下之前的一些基础java知识点.本想着随便看看,然而就发现有了意外收获.比如本文所讲HashMap遍历的四种常用方式. 大伙们一起学习一起进步,记得点赞关 ...
最新文章
- Dynamics CRM 导入导出数据
- 分享Silverlight/WPF/Windows Phone一周学习导读(10月16日-10月22日)
- 居民信息管理系统java_基于jsp的社区住户信息管理系统-JavaEE实现社区住户信息管理系统 - java项目源码...
- Centos7 把php5.4升级到php5.6
- 超级计算机TOP500、green500、graph500最新排名(2012.11)
- java函数改变参数值_Java函数参数值正在改变
- VR厂商,你们考虑过霍金的感受吗?
- 简单的抓包_学习笔记
- 微信小程序使用阿里巴巴矢量库图标
- 【Javafx】关于属性绑定需要在动画设置之后
- 勇者斗恶龙10 android,《勇者斗恶龙》系列35周年纪念直播情报汇总
- Android NFC基础
- 水文专业对计算机要求,来了来了,高考志愿这么填!
- getline()函数的几点疑惑
- 【Unity】使用 [xxx] 标记类和方法
- 【专业数据】二.2020~2022年北京交通大学【信息与通信工程】专业复试线/分数线差/计划招生数/复试数/录取数/复试比例/录取率
- 练手练到阅文集团作家中心了,python crawlspider 二维抓取学习
- python学习36:给IDLE添加行号(采用IDLEX的LineNumbers.py)python3.8也可以用(亲测有效)
- 漫谈深度学习在Super Resolution(超分辨率)领域上的应用
- php正态分布,如何在PHP中生成累积正态分布