- 浏览: 17356 次
- 性别:
- 来自: 南京
文章分类
最新评论
基于切面的AOP编程
通过Advice,可以创建方法前,后,环绕之类的增强,但是这是类级别的增强,如果想要深入到方法级别,就需要配合使用切点Pointcut。Advice和Pointcut组合就形成了一个切面。切面增强就是基于方法层面的。
1.切点(Pointcut)
用于过滤类,getClassFilter()返回ClassFilter类,在这个类里面有一个方法用于判断该对象是否满足匹配条件,boolean matches(Class<?> clazz)。
用于过滤方法,getMethodMatcher()返回MethodMatcher,在该类里面有boolean matches(Method method, Class<?> targetClass)用于静态匹配方法,boolean matches(Method method, Class<?> targetClass, Object[] args)用于动态匹配。
2 切点的分类
静态方法切点又分两种
3 切面
切面分三种
而PointcutAdvisor又分为以下6种
4 例子
准备基础类和一个增强类
4.1 静态方法匹配:
因为GreetingAdvisor类中已经包含切点信息,所以只要配置增强类即可。
测试:
输出:
只有Waiter类的greetTo方法被织入增强
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.John
waiter greet to John...
waier serving to John...
seller greet to John...
4.2 正则匹配方法名增强
输出:
只有greetTo方法被织入增强
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.John
waiter greet to John...
waier serving to John...
4.3 动态方法匹配
动态方法匹配之前都会先进性静态方法匹配,如果失败才会进行
输出:
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.serveTo做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.toString做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.clone做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做动态检查。
waiter greet to Peter...
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.serveTo做静态检查。
waier serving to Peter...
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做动态检查。
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.John
waiter greet to John...
waier serving to John...
4.4 流程切面
对配置在某一个类中的某一个方法中直接或间接使用的类进行增强
输出:
只有流程切点中的才会被织入增强
waier serving to Peter...
waiter greet to Peter...
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.Peter
waiter greet to Peter...
com.firethewhole.maventest07.advisor.Waiter.serveTo
How are you! Mr.Peter
waier serving to Peter...
4.5 复合增强
输出:
只有流程切点中的方法名为greetTo才会被织入增强
waier serving to Peter...
waiter greet to Peter...
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.Peter
waiter greet to Peter...
waier serving to Peter...
4.6 引介增强
引介增强是类级别的织入,主要的类有DefaultIntroductionAdvisor,配置方法如下:
通过Advice,可以创建方法前,后,环绕之类的增强,但是这是类级别的增强,如果想要深入到方法级别,就需要配合使用切点Pointcut。Advice和Pointcut组合就形成了一个切面。切面增强就是基于方法层面的。
1.切点(Pointcut)
用于过滤类,getClassFilter()返回ClassFilter类,在这个类里面有一个方法用于判断该对象是否满足匹配条件,boolean matches(Class<?> clazz)。
用于过滤方法,getMethodMatcher()返回MethodMatcher,在该类里面有boolean matches(Method method, Class<?> targetClass)用于静态匹配方法,boolean matches(Method method, Class<?> targetClass, Object[] args)用于动态匹配。
2 切点的分类
- StaticMethodMatcherPointcut 静态方法切点
- DynamicMethodMatcherPointcut 动态方法切点
- AnnotationMatchingPointcut 注解切点
- AspectJExpressionPointcut 支持AspectJ语法的表达式切点
- ControlFlowPointcut 流程切点
- ComposablePointcut 复合切点
静态方法切点又分两种
- NameMatchMethodPointcut 用于方法名匹配
- JdkRegexpMethodPointcut 用于正则匹配
3 切面
切面分三种
- Advisor 一般切面,仅包含一个增强方法,不包含切点信息
- PointcutAdvisor 包含切点的切面,用起来比较灵活
- IntroductionAdvisor 引介切面
而PointcutAdvisor又分为以下6种
- DefaultPointcutAdvisor 最常用的切面,可以通过任意组合切点和增强构建切面
- NameMatchMethodPointcutAdvisor 通过方法名来定义切面
- RegexpMethodPointcutAdvisor 通过正则表达式匹配方法名来定义切面
- StaticMethodMatcherPointcutAdvisor 默认情况下,匹配所有目标类
- AspectJExpressionPointcutAdvisor 用AspectJ切点表达式来匹配
- AspectJPointcutAdvisor 用AspectJ语法来匹配
4 例子
准备基础类和一个增强类
public class Waiter { public void greetTo(String name) { System.out.println("waiter greet to " + name + "..."); } public void serveTo(String name) { System.out.println("waier serving to " + name + "..."); } } public class Seller { public void greetTo(String name) { System.out.println("seller greet to " + name + "..."); } }个 // 前置增强 public class GreetingBeforeAdvice implements MethodBeforeAdvice { public void before(Method method, Object[] args, Object obj) throws Throwable { System.out.println(obj.getClass().getName() + "." + method.getName()); String clientName = (String) args[0]; System.out.println("How are you! Mr." + clientName); } }
4.1 静态方法匹配:
public class GreetingAdvisor extends StaticMethodMatcherPointcutAdvisor { public boolean matches(Method method, Class<?> targetClass) { return "greetTo".equals(method.getName()); } public ClassFilter getClassFilter() { return new ClassFilter() { public boolean matches(Class<?> clazz) { return Waiter.class.isAssignableFrom(clazz); } }; } }
因为GreetingAdvisor类中已经包含切点信息,所以只要配置增强类即可。
<bean id="waiterTarget" class="com.firethewhole.maventest07.advisor.Waiter"/> <bean id="sellerTarget" class="com.firethewhole.maventest07.advisor.Seller"/> <bean id="greetingAdvice" class="com.firethewhole.maventest07.advisor.GreetingBeforeAdvice"/> <bean id="greetingAdvisor" class="com.firethewhole.maventest07.advisor.GreetingAdvisor" p:advice-ref="greetingAdvice"/> <bean id="parent" abstract="true" class="org.springframework.aop.framework.ProxyFactoryBean" p:interceptorNames="greetingAdvisor" p:proxyTargetClass="true"/> <bean id="waiter" parent="parent" p:target-ref="waiterTarget"/> <bean id="seller" parent="parent" p:target-ref="sellerTarget"/>
测试:
String configPath = "com/firethewhole/maventest07/advisor/beans.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath); Waiter waiter = (Waiter) ctx.getBean("waiter"); Seller seller = (Seller) ctx.getBean("seller"); waiter.greetTo("John"); waiter.serveTo("John"); seller.greetTo("John");
输出:
只有Waiter类的greetTo方法被织入增强
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.John
waiter greet to John...
waier serving to John...
seller greet to John...
4.2 正则匹配方法名增强
<bean id="regexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" p:advice-ref="greetingAdvice"> <property name="patterns"> <list><value>.*greet.*</value></list> </property> </bean> <bean id="waiter1" class="org.springframework.aop.framework.ProxyFactoryBean" p:interceptorNames="regexpAdvisor" p:target-ref="waiterTarget" p:proxyTargetClass="true"/>
Waiter waiter1 = (Waiter) ctx.getBean("waiter1"); waiter1.greetTo("John"); waiter1.serveTo("John");
输出:
只有greetTo方法被织入增强
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.John
waiter greet to John...
waier serving to John...
4.3 动态方法匹配
动态方法匹配之前都会先进性静态方法匹配,如果失败才会进行
public class GreetingDynamicPointcut extends DynamicMethodMatcherPointcut { private static List<String> specialClientList = new ArrayList<String>(); static { specialClientList.add("John"); specialClientList.add("Tom"); } public ClassFilter getClassFilter() { return new ClassFilter() { public boolean matches(Class<?> clazz) { System.out.println("调用getClassFilter()对" + clazz.getName() + "做静态检查。"); return Waiter.class.isAssignableFrom(clazz); } }; } public boolean matches(Method method, Class<?> clazz) { System.out.println("调用matches(method,clazz)对" + clazz.getName() + "." + method.getName() + "做静态检查。"); return "greetTo".equals(method.getName()); } public boolean matches(Method method, Class<?> clazz, Object[] args) { System.out.println("调用matches(method,clazz)对" + clazz.getName() + "." + method.getName() + "做动态检查。"); String clientName = (String) args[0]; return specialClientList.contains(clientName); } }
<bean id="greetingDynamicPointcut" class="com.firethewhole.maventest07.advisor.GreetingDynamicPointcut"/> <bean id="dynamicAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor" p:pointcut-ref="greetingDynamicPointcut" p:advice-ref="greetingAdvice"/> <bean id="waiter2" class="org.springframework.aop.framework.ProxyFactoryBean" p:interceptorNames="dynamicAdvisor" p:target-ref="waiterTarget" p:proxyTargetClass="true"/>
Waiter waiter2 = (Waiter) ctx.getBean("waiter2"); waiter2.greetTo("Peter"); waiter2.serveTo("Peter"); waiter2.greetTo("John"); waiter2.serveTo("John");
输出:
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.serveTo做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.toString做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.clone做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做动态检查。
waiter greet to Peter...
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.serveTo做静态检查。
waier serving to Peter...
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做动态检查。
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.John
waiter greet to John...
waier serving to John...
4.4 流程切面
对配置在某一个类中的某一个方法中直接或间接使用的类进行增强
public class WaiterDelegate { private Waiter waiter; public void setWaiter(Waiter waiter) { this.waiter = waiter; } public void service(String name) { waiter.greetTo(name); waiter.serveTo(name); } }
<bean id="controlFlowPointcut" class="org.springframework.aop.support.ControlFlowPointcut"> <constructor-arg type="java.lang.Class" value="com.firethewhole.maventest07.advisor.WaiterDelegate"/> <constructor-arg type="java.lang.String" value="service"/> </bean> <bean id="controlFlowAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor" p:pointcut-ref="controlFlowPointcut" p:advice-ref="greetingAdvice"/> <bean id="waiter3" class="org.springframework.aop.framework.ProxyFactoryBean" p:interceptorNames="controlFlowAdvisor" p:target-ref="waiterTarget" p:proxyTargetClass="true"/>
Waiter waiter3 = (Waiter) ctx.getBean("waiter3"); WaiterDelegate wd = new WaiterDelegate(); wd.setWaiter(waiter3); waiter3.serveTo("Peter"); waiter3.greetTo("Peter"); wd.service("Peter");
输出:
只有流程切点中的才会被织入增强
waier serving to Peter...
waiter greet to Peter...
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.Peter
waiter greet to Peter...
com.firethewhole.maventest07.advisor.Waiter.serveTo
How are you! Mr.Peter
waier serving to Peter...
4.5 复合增强
public class GreetingComposablePointcut { public Pointcut getIntersectionPointcut() { ComposablePointcut cp = new ComposablePointcut(); Pointcut pt1 = new ControlFlowPointcut(WaiterDelegate.class, "service"); Pointcut pt2 = new NameMatchMethodPointcut(); ((NameMatchMethodPointcut)pt2).addMethodName("greetTo"); return cp.intersection(pt1).intersection(pt2); } }
<bean id="gcp" class="com.firethewhole.maventest07.advisor.GreetingComposablePointcut"/> <bean id="compsableAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor" p:pointcut="#{gcp.getIntersectionPointcut()}" p:advice-ref="greetingAdvice"/> <bean id="waiter4" class="org.springframework.aop.framework.ProxyFactoryBean" p:interceptorNames="compsableAdvisor" p:target-ref="waiterTarget" p:proxyTargetClass="true"/>
Waiter waiter4 = (Waiter) ctx.getBean("waiter4"); WaiterDelegate wd2 = new WaiterDelegate(); wd2.setWaiter(waiter4); waiter4.serveTo("Peter"); waiter4.greetTo("Peter"); wd2.service("Peter");
输出:
只有流程切点中的方法名为greetTo才会被织入增强
waier serving to Peter...
waiter greet to Peter...
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.Peter
waiter greet to Peter...
waier serving to Peter...
4.6 引介增强
引介增强是类级别的织入,主要的类有DefaultIntroductionAdvisor,配置方法如下:
<bean id="introduceAdvisor" class="org.springframework.aop.support.DefaultIntroductionAdvisor"> <constructor-arg> <bean class="com.firethewhole.maventest07.introduce.ControllablePerformanceMonitor/> </constructor-arg> </bean>
- maventest07.zip (56.3 KB)
- 下载次数: 0
发表评论
-
Spring基础:数据访问(3)
2017-01-15 09:29 440在开源世界里,有很多ORM框架使用,比如Hibernate,还 ... -
Spring基础:数据访问(2)
2016-12-31 10:55 531上一篇主要将了Spring JDB ... -
Spring基础:数据访问(1)
2016-12-27 08:22 383Spring JDBC通过模板和回调机制大大降低了使用JDBC ... -
Spring基础:AOP编程(5)
2016-11-30 07:35 379基于Schema的AOP编程 基于AspectJ的AOP编程已 ... -
Spring基础:AOP编程(4)
2016-11-27 12:17 413基于AspectJ的AOP编程 AspectJ的切点函数非常 ... -
Spring基础:AOP编程(2)
2016-11-15 23:40 411基于ProxyFactory的AOP编程 Spring只支持 ... -
Spring基础:AOP编程(1)
2016-11-14 01:08 416Java编程中的代理 Spring以IoC为基础,发展了另外 ... -
Spring基础:IoC容器(2)
2016-11-12 10:00 448容器注入类型 最常见的注入类型是字面值注入,像String和 ... -
Spring基础:IoC容器(1)
2016-11-10 08:15 404在IoC容器中装配Bean 4.1.2.RELEASE版本的 ... -
Spring基础:稍显复杂的Spring Hello World
2016-11-01 00:59 387本文参考《Spring 3.x企业应用开发》这本书完成,作为自 ... -
使用Eclipse创建基于Maven Web工程
2016-06-06 19:19 448第一步:创建一个maven-webapp类型的工程 完 ...
相关推荐
在本篇博客“Spring基础:AOP编程(4)”中,我们将深入探讨Spring框架中的面向切面编程(Aspect-Oriented Programming,简称AOP),这是一个强大的功能,它允许我们在不修改原有业务代码的情况下,实现对系统中横切...
这篇博客“Spring基础:AOP编程(1)”可能介绍了AOP的基础知识及其在Spring中的实现。 面向切面编程(AOP)是一种编程范式,旨在减少代码的重复性,提高模块间的解耦度。AOP通过将横切关注点(如日志、事务管理、...
在本篇关于“Spring基础:AOP编程(2)”的文章中,我们将深入探讨Spring框架中的面向切面编程(Aspect-Oriented Programming, AOP),这是一种强大的设计模式,它允许我们分离关注点,尤其是那些横切关注点,如日志、...
在本篇博文中,我们将深入探讨Spring框架中的一个核心特性——面向切...通过以上介绍,我们对Spring中的AOP编程有了基本了解。在实际开发中,AOP可以帮助我们更好地组织代码,降低复杂度,提高代码的可维护性和可读性。
Spring AOP是在Spring框架的基础上实现的一种面向方面编程机制。 1. **方面(Aspect)**:这是AOP的核心概念之一,指代一个关注点的模块化,该关注点可能会横切多个对象。例如事务管理就是一个典型的横切关注点,...
Spring AOP,全称Aspect Oriented Programming(面向切面编程),是Spring框架的重要组成部分,它扩展了传统的面向对象编程(OOP),使得开发者能够更好地处理系统中的横切关注点,如日志、事务管理、权限控制等。...
在讨论Spring AOP(面向切面编程)时,首先需要理解几个核心概念。Spring AOP 是Spring框架提供的一个功能模块,它允许开发者将横切关注点(cross-cutting concerns)从业务逻辑中解耦出来,通过在方法调用前后进行...
根据提供的文件内容,可以提取出以下知识点: ...文档中提到的实践示例,例如前置通知、后置通知、返回通知、异常通知和环绕通知的具体编码实现,都是通过具体的代码示例来说明如何在Spring中应用AspectJ进行AOP编程。
Spring Boot AOP(面向切面编程)是一种强大的设计模式,它允许我们在不修改现有代码的情况下,插入额外的功能或监控代码。在Spring框架中,AOP主要用于日志记录、事务管理、性能统计等场景。本示例是关于如何在...
Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的重要组成部分,它扩展了传统的面向对象编程,使得开发者可以方便地实现横切关注点,如日志、事务管理、性能监控等。在Spring中,AOP通过代理...
其中,面向切面编程(Aspect Oriented Programming,简称AOP)是Spring的重要特性之一,它极大地简化了代码中的横切关注点,如日志、事务管理等。本文将深入Spring源码,探索AOP的实现原理。 首先,我们需要理解AOP...
面向切面编程(AOP)是一种编程范式,它旨在减少代码中的重复部分,特别是那些与核心业务逻辑无关但又必须处理...同时,通过分析和操作`springAOP`压缩包中的示例代码,可以更直观地了解AOP在Spring框架中的具体实现。
为了在Spring中进行AOP编程,我们需要一些特定的JAR包。以下是对这些关键组件的详细说明: 1. **Spring核心包**: - `spring-core.jar`: 这是Spring框架的基础,包含了IoC(Inversion of Control,控制反转)容器...
在Spring框架中,AOP(面向切面编程)是一种强大的设计模式,它允许开发者将关注点从核心业务逻辑中分离出来,例如日志记录、事务管理等。本教程将通过模拟Spring AOP来阐述如何实现一个简单的切面编程。我们将讨论...
在IT领域,Spring框架是一个广泛使用的Java应用框架,它提供了许多功能,包括依赖注入、面向切面编程(AOP)等。"spring-aop-jar"这个主题涉及到Spring框架中的核心组件之一——Spring AOP。这里我们将深入探讨...
为了说明Spring的AOP原理,本人使用代理模式中的动态代理完成演示AOP编程的原理的演示。相信,如果你耐心看完整个程序(几乎一行注释一行代码),那么你对Spring这个东西就不是觉得有什么神秘了! 阅读对象:凡是喜爱...
Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的重要组成部分,它提供了一种在不修改源代码的情况下,对程序进行功能增强的技术。AOP的核心概念是切面(Aspect)、通知(Advice)、连接点...
Spring AOP,全称Aspect-Oriented Programming(面向切面编程),是Spring框架的一个重要特性,主要用于解决程序中的横切关注点,如日志、事务管理、安全性等。AOP通过将这些关注点与核心业务逻辑分离,实现了代码的...