一、通过代理工厂模式配置通知
①、前置通知、后置通知:
定义某接口:ISomeService,并自定义方法
public interface ISomeService {
public void tran() throws Exception;
public void log(); }
定义类 实现该接口,并重写方法:
public class SomeService implements ISomeService{ public void tran() throws Exception{
System.out.println("开启事务!!"); } public void log() {
System.out.println("记录日志!!");
}
定义前置通知类,并实现MethodBeforeAdvice该接口
public class MyBefore implements MethodBeforeAdvice{ public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
System.out.println("==before=="); }
定义后置通知类,并实现AfterReturningAdvice该接口
public class MyAfter implements AfterReturningAdvice{ public void afterReturning(Object arg0, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
System.out.println("==after=="); }
配置Spring配置文件applicationContext.xml:
代理工厂:ProxyFactoryBean
测试类:
实现效果:
② 环绕通知 MethodInterceptor
环绕增强在目标方法的前后都可以织入增强处理。环绕增强是功能最强大的强大处理。Spring把目标方法的控制权全部交给了他。在环绕增强处理中,可以获取或修改目标方法的参数、返回值、可以对它进行异常处理,甚至可以决定目标方法是否执行。
配置Spring文件:
<!-- 环绕增强 -->
<bean id="some" class="cn.happy.entity.SomeService"></bean> <bean id="arround" class="cn.happy.arround.MyInterceptor"></bean> <bean id="factory" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="some"></property>
<property name="interceptorNames" value="arround"></property>
</bean>
实现效果:
通过MethodInterceptor接口实现了环绕增强。该接口要求实现invoke()方法,其参数MethodInvocation不但封装目标方法及其参数组,还封装了被代理目标对象。通过proceed()方法可以调用目标对象的相应方法,从而实现对目标方法的完全控制!
③异常通知:
特点是在目标方法抛出异常时织入增强处理。通过ThrowsAdvice接口实现异常抛出增强,但ThrowsAdvice接口中并没有定义任何方法,但是我们在定义异常抛出的增强方法时必须遵守以下方法签名:
void afterThrowing([Method method,Object[]arguments,Object target,] Throwable ex)
实现类出现异常情况下:
Spring配置文件:
<!-- 异常通知 -->
<bean id="some" class="cn.happy.entity.SomeService"></bean> <bean id="throws" class="cn.happy.throwsAdvice.MyThrows"></bean> <bean id="factory" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="some"></property>
<property name="interceptorNames" value="throws"></property>
</bean>
测试类:
若将异常抛给上级处理,则在控制台通过,单测报错,若将异常手动抛出,则相反
@Test
public void proxyTest(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
ISomeService ser=(ISomeService) ctx.getBean("factory");
//ser.tran();
try {
ser.tran();
} catch (Exception e) {
e.printStackTrace();
}
ser.log(); }
二、顾问Advisor
顾问Advisor是Spring提供的另一种切面。其可以完成更为复杂的切面织入功能。PointcutAdvisor是顾问的一种,可以指定具体的切入点。顾问将通知进行了包装,会根据不同的通知类型,在不同的时间点,将切面织入到不同的切入点。
PointcutAdvisor接口有两个较为常用的实现类:
*:NameMatchMethodPointcutAdvisor 名称匹配方法切入点顾问
*: RegexpMethodPointcutAdvisor 正则表达式匹配方法切入点顾问
<property name="pattern" value=".*do.*"></property> 表示方法全名(包名,接口名,方法名)
运算符名称意义:
. 点号 表示任意单个字符
+ 加号 表示前一个字符出现一次或者多次
* 星号 表示前一个字符出现0次或者多次
如何实现:
同理:定义接口和实现类,并自定义方法。以及前置增强的类。关键点在Spring配置文件
①名称匹配方法切入点顾问
② 正则表达式匹配方法切入点顾问
三、自动代理生成器
注意:默认Advisor自动代理生成器,切面只能是顾问,对所有的对象都增强
两种实现方式:
① 默认Advisor自动代理生成器 DefaultAdvisorAutoProxyCreator
② BeanName自动代理生成器 BeanNameAutoProxyCreator
在这里 无需配置代理工厂bean,测试类getBean()取的id是配置文件的被代理对象
切面只能是顾问的情况下:
实现效果:
既可以是通知也可以是顾问的情况下:
实现效果:
测试类:
public class Test01 {
@Test
public void proxyTest(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
ISomeService ser=(ISomeService) ctx.getBean("some");
ser.tran();
ser.log(); }
四、Spring的经典AOP配置方案、使用的是Aspectj第三方框架,实现了AOP思想。注解配置的AOP,纯POJO <aop:config>
具体步骤:
① 在项目中添加SpringAOP相关的JAR文件
②使用注解定义前置增强和后置增强实现日志功能
③编写Spring配置文件,织入注解定义的增强
④编写代码获取带有增强处理的业务对象
核心JAR包:
实现思路:
1、定义接口实现类,并重写该方法
public interface ISomeService {
public void list();
}
public class SomeService implements ISomeService{ public void list() {
System.out.println("SomeService.list()");
} }
2、通过注解实现增强,自定义类
使用@Aspect注解将该类定义为切面,并且使用@Before注解将该方法定义为前置增强,增强定义完后,就可以在Spring配置文件中织入使用注解定义的增强了
@Aspect public class MyAspectj { @Before(value = "execution(* *..service.*.*(..))") public void MyBeforeAdvice(){
System.out.println("==before==");
}
}
3、Spring配置文件
4、进行测试:
public class Test01 {
@Test
public void proxyTest(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
ISomeService ser=(ISomeService) ctx.getBean("some");
ser.list(); }
实现效果:
※※※补充点:
切入点表达式:
execution(【modifiers-pattern?】 访问修饰符
ret-type-pattern 返回值类型
【declaring-type-pattern?】 全限定性类名
name-pattern(param-pattern) 方法名(参数名) 包名.类型名.方法名
【throws-pattern?】) 抛出异常类型
public void doLog(String log){
}
切入点表达式要匹配的对象就是目标方法的方法名。所以,execution表达式中明显就是方法的签名。
注意:表达式中加[]的部分表示可省略部分,各部分间用空格分开。在其中可以使用以下符号:
符号意义:
* 0至多个任意字符
.. 用在方法参数中,表示任意多个参数
用在包名后,表示当前包及其子包路径
+ 用在类名后,表示当前类及其子类
用在接口后,表示当前接口及其实现类
案例:
execution(public * *(..)) 指定切入点为:任意公共方法
execution(* set*(..)) 指定切入点为:任何一个以"set"开始的方法
Spring AOP深入剖析的更多相关文章
-
Spring AOP 深入剖析
AOP是Spring提供的关键特性之一.AOP即面向切面编程,是OOP编程的有效补充.使用AOP技术,可以将一些系统性相关的编程工作,独立提取出来,独立实现,然后通过切面切入进系统.从而避免了在业务逻 ...
-
[转载]Spring AOP 深入剖析
转载自 http://www.cnblogs.com/digdeep/p/4528353.html 多谢@digdeep AOP是Spring提供的关键特性之一.AOP即面向切面编程,是OOP编程的有 ...
-
Spring AOP 实现原理与 CGLIB 应用
https://www.ibm.com/developerworks/cn/java/j-lo-springaopcglib/ AOP(Aspect Orient Programming),也就是面向 ...
-
Spring AOP 实现原理与 CGLIB 应用--转
AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓存.对象池管理等.AOP 实现的关键就在于 ...
-
spring AOP 之一:spring AOP功能介绍
一.AOP简介 AOP:是一种面向切面的编程范式,是一种编程思想,旨在通过分离横切关注点,提高模块化,可以跨越对象关注点.Aop的典型应用即spring的事务机制,日志记录.利用AOP可以对业务逻辑的 ...
-
【转】Spring AOP 实现原理与 CGLIB 应用
AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓存.对象池管理等.AOP 实现的关键就在于 ...
-
spring AOP详解四
AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓存.对象池管理等.AOP 实现的关键就在于 ...
-
Spring源码剖析6:Spring AOP概述
原文出处: 五月的仓颉 我们为什么要使用 AOP 前言 一年半前写了一篇文章Spring3:AOP,是当时学习如何使用Spring AOP的时候写的,比较基础.这篇文章最后的推荐以及回复认为我写的对大 ...
-
Spring源码剖析7:AOP实现原理详解
前言 前面写了六篇文章详细地分析了Spring Bean加载流程,这部分完了之后就要进入一个比较困难的部分了,就是AOP的实现原理分析.为了探究AOP实现原理,首先定义几个类,一个Dao接口: pub ...
随机推荐
-
C++中的迭代器
C++STL中的迭代器 "指针"对所有C/C++的程序员来说,一点都不陌生.在接触到C语言中的malloc函数和C++中的new函数后,我们也知道这两个函数返回的都是一个指针,该指 ...
-
I.MX6 默认打开 USB adb
/***************************************************************************** * I.MX6 默认打开 USB adb ...
-
如何学习java ee
来看看Sun给出的J2EE 相关技术主要分为几大块. 1. Web Service技术 - Java API for XML Processing (JAXP) - Java API for XM ...
-
Threading Module源码概述(二)
在threading 模块中,提供了列举当前所有子线程的操作.threading.enumerate.这个操作很简单,就是将_active和_limbo中维护的线程集合的信息输出. def enume ...
-
Exiting the Matrix: Introducing Metasploit&#39;s Hardware Bridge
Metasploit is an amazing tool. You can use it to maneuver through vast networks, pivoting through se ...
-
java错误分类
IllegalArgumentException 回直接crashError
-
amazeUI的confirm控件记录缓存问题的解决办法
场景:列表行每行都有删除按钮,点击删除按钮将行记录的id传给js方法,js方法中调用amazeui的confirm控件,确认删除function通过ajax执行删除行为. 问题现象:每次删除列表第一行 ...
-
【Java面试题】17 如何把一个逗号分隔的字符串转换为数组? 关于String类中split方法的使用,超级详细!!!
split 方法:将一个字符串分割为子字符串,然后将结果作为字符串数组返回. stringObj.split([separator],[limit])参数:stringObj 必选项.要被分解的 ...
-
[Codeup 25481] swan
莫名其妙还找到了另一个铟炔锶烃的OJ : Codeup墓地 25481: swan 时间限制: 1 Sec 内存限制: 128 MB献花: 86 解决: 13[献花][花圈][TK题库] 题目描述 ...
-
(LeetCode 49)Anagrams
Given an array of strings, return all groups of strings that are anagrams. Note: All inputs will be ...