原创内容,转载请注明出处
首先先重复一下上篇动态代理所说的例子,如下。
先举一个编程的例子。比如一个功能(DB接口),实现的是对数据库的一些增删改查的功能(方法名分别是add、delete、update、find),现在由于业务的变更,需要在对数据库操作完成后增加日志记录功能(Log接口),记录当前人对数据库进行了什么样的操作,操作是否成功。这时首先想到的实现方式应该是在add、delete、update、find的方法内部最后面增加记录日志的实现方式。如果又因为业务的变更,还需要判断这个人是否有该操作的权限(Permission接口),如果没有,则不让该用户进行操作,这时我们又得修改所有的数据库操作的方法,在每个方法执行前校验用户的权限。
用一句话去概括总结上述例子,我总结的是在什么地方(可指在哪个包下的哪个类的哪个方法)去增强什么样的功能(可表示日志功能或者事务功能)。首先先来理清楚以下几个概念。
Advice通知:指上例所说的日志、权限功能,可以简单理解为要增加什么样的功能(Log、Permission)。
JoinPoint连接点:指上例所说的add方法或者update方法,可以理解为在哪个点进行增加功能,表示一个方法的执行。
Pointcut切入点:指上例所说的add、delete、update、find方法,是JoinPoint的集合,表示多个方法的集合。可以简单理解为在什么地方增加功能。
Advisor通知器:指在什么样的地方增加什么样的功能,也就是将Advice和Pointcut联系起来。
目标对象(Target Object):指需要增强功能的对象,也就是上例的包含add、delete、update、find方法的对象(DB接口的实现类)。
Introduction引入:和Advice不同,Advice是指在生成后的代理对象在含有目标对象的方法功能外,还在方法前后添加一些额外功能,比如记录日志等。引入是指动态的给某个接口类实现继承其他接口功能,比如上例中的接口类(DB接口)含有add、delete、update、find功能,现在要要为该接口类动态的引入其他接口功能,比如DBAll接口的deleteAll功能,这时生成后的代理对象则相当于实现了DBAll接口。
1、Advice通知
通知类继承图如下
如上图可以看出Advice主要分为四个接口子类,一个是AfterAdvice(在目标方法执行后增加功能)、BeforeAdvice(在目标方法执行前增加功能)、DynamicIntroductionAdvice、Interceptor(拦截器)。AfterAdvice的子接口由AfterReturningAdvice和ThrowsAdvice,AfterReturningAdvice接口类有一个afterReturning方法,在目标方法执行完后才执行;ThrowsAdvice接口类是在目标方法执行后抛出异常时执行。BeforeAdvice的子接口有MethodBeforeAdvice,MethodBeforeAdvice接口有一个before方法,在目标方法执行前执行。
2、Pointcut切入点
Pointcut切入点类继承图如下
在Pointcut接口中,有两个方法,一个是getClassFilter(获取过滤类的类),一个是getMethodMatcher(获取过滤方法的类),从这里应该可以看出Pointcut的作用。
Pointcut主要分类动态切入点和静态切入点,静态切入点在代理创建时执行一次,之后就会缓存下来,而动态切入点是在每次执行前都执行,故而静态切入点性能高。
Pointcut类可参考子类实现JdkRegexpMethodPointcut(按正则表达式匹配方法),NameMatchMethodPointcut(按方法名去匹配)。
3、Advisor通知器
Advisor通知器主要包含两大类,一个是引入通知器(IntroductionAdvisor),一个是切点通知器(PointcutAdvisor)。如下类继承图
4、Spring Aop
Spring Aop主要实现是通过Jdk动态代理和Cglib动态代理来实现的,这个在Spring动态代理篇已经有讲过。在Spring动态代理篇幅中是使用ProxyFactoryBean中实现的增强功能的实现是通过实现Spring的Advise接口完成的,这样会导致需要增强的功能类和Spring耦合在一起,现在可以通过Spring Aop标签来配置,达到Spring Aop功能。
创建业务Manager接口类,代码如下
package com.test.aop; public interface Manager { public abstract void insert(String sql); public abstract void find(String sql); public abstract void findAll(); }
创建业务实现类ManagerImpl,代码如下
package com.test.aop; public class ManagerImp implements Manager { public void insert(String sql){ System.out.println("--------执行插入语句"+sql+"----------"); } public void find(String sql) { System.out.println("--------执行查询语句"+sql+"----------"); } public void findAll() { System.out.println("--------查询所有记录----------"); } }
添加记录日志功能类Log,代码如下
package com.test.aop; public class Log { public void writelog(){ System.out.println("-----------记录日志--------"); } }
添加校验权限的功能类Check,代码如下
package com.test.aop; public class Check { public void hasPermission(){ System.out.println("-----------校验是否有权限操作--------"); } }
添加Spring配置文件bean.xml,需要在所有方法前添加校验用户权限功能,在insert插入方法后增加记录日志功能。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 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"> <!-- 测试Spring aop --> <bean id="manager" class="com.test.aop.ManagerImp" lazy-init="false"/> <bean id="log" class="com.test.aop.Log"/> <bean id="check" class="com.test.aop.Check"/> <aop:config> <aop:pointcut expression="execution(* com.test.aop.Manager.insert(..))" id="target"/> <aop:pointcut expression="execution(* com.test.aop.Manager.find*(..))" id="findAllTarget"/> <aop:aspect ref="log"> <aop:after method="writelog" pointcut-ref="target"/> </aop:aspect> <aop:aspect ref="check"> <aop:before method="hasPermission" pointcut-ref="target"/> </aop:aspect> <aop:aspect ref="check"> <aop:before method="hasPermission" pointcut-ref="findAllTarget"/> </aop:aspect> </aop:config> </beans>
添加Junit测试代码
/** * 测试Spring Aop */ @Test public void testSpringAop(){ ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml"); Manager manager = (Manager) ctx.getBean("manager"); System.out.println("------------------------测试插入方法---------------------------"); manager.insert("insert into sp_user(1,2,'1111')"); System.out.println("------------------------测试查询所有数据的查询方法---------------------------"); manager.findAll(); System.out.println("------------------------测试查询方法---------------------------"); manager.find("select * from sp_user"); }
测试结果如下
如上,即使增强功能类与Spring达到松散耦合的效果。
源代码如附件
相关推荐
《Spring源码分析——BeanFactory》 在Java的IoC(Inversion of Control)和DI(Dependency Injection)领域,Spring框架扮演着至关重要的角色。BeanFactory是Spring的核心组件之一,它是容器的基石,负责管理应用...
《Spring源码分析——ApplicationContext》 在Java世界中,Spring框架是不可或缺的一部分,它以其强大的IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)特性,极大地...
分析Spring源码有助于深入理解其动态代理的工作原理。例如,可以查看`org.springframework.aop.framework.JdkDynamicAopProxy`和`org.springframework.aop.framework.CglibAopProxy`这两个类,它们分别实现了JDK和...
Spring作为Java领域最广泛应用的框架之一,其核心组件包括依赖注入(Dependency Injection,DI)、AOP(面向切面编程)、资源管理、事件处理以及bean的生命周期管理等。这些组件构成了Spring应用程序的基础,使得...
在深入理解 Spring AOP 的源码时,需要熟悉 Spring IoC 的工作原理,以及 AOP 相关的概念,如切点表达式、通知类型等。了解这些基础知识可以帮助我们更好地掌握 Spring AOP 的实现细节。在分析源码时,可以参考作者...
《Spring5 源码分析(第 2 版)》是某Tom老师精心编写的深度解析文档,旨在帮助读者全面理解Spring5的核心机制和设计理念。Spring作为Java领域最为广泛应用的框架之一,其源码的深入理解对于开发者来说至关重要。这篇...
Struts2作为MVC框架负责控制层,而Spring则提供了全面的依赖注入(DI)和面向切面编程(AOP)功能。将这两者集成可以实现强大的应用架构。然而,集成过程中可能会遇到一些问题,尤其是当涉及到Spring的AOP时。 首先...
《Spring5 源码分析(第 2 版)》是针对Spring框架第五个主要版本的深度解析著作,由知名讲师倾心打造,旨在帮助读者深入理解Spring框架的内部工作机制,提升对Java企业级应用开发的专业技能。本书涵盖了Spring框架的...
本压缩包“Spring源码解析”提供了对Spring框架核心组件——IOC(Inversion of Control,控制反转)、AOP(Aspect Oriented Programming,面向切面编程)以及Transaction(事务管理)的源码分析,帮助开发者更全面地...
在源码分析的过程中,读者会深入理解Spring的内部工作机制,例如如何解析配置、如何创建bean实例、如何实现AOP代理等。这将有助于开发者编写更高效、更健壮的代码,也能为参与Spring的扩展或定制打下坚实基础。 总...
### Spring 源码分析——设计模式篇 #### 一、引言 Spring框架作为Java企业级开发领域中不可或缺的一部分,其内部集成了多种设计模式,不仅有助于提高系统的可维护性和扩展性,还能够帮助开发者更好地理解和应用...
本篇文章将深入探讨如何使用Spring AOP实现性能监控器,并通过源码分析来理解其工作原理。 首先,我们要了解AOP的核心概念——切面(Aspect)、通知(Advice)、连接点(Join Point)、切入点(Pointcut)和织入...
通过对Spring AOP源码的深入分析,我们可以了解到其内部是如何通过代理模式和反射技术实现对方法调用的拦截,以及如何解析和执行切点表达式,理解通知的执行流程等。这些深入理解对于优化性能、排查问题以及自定义...
SpringBoot 源码解析——源码模块功能分析 SpringBoot 源码解析是指对 SpringBoot 框架的源码进行深入分析和研究,以了解框架的内部机制和工作原理。源码模块是 SpringBoot 框架的核心组成部分,它们之间的交互和...
总的来说,《Spring高级源码分析》将带你深入Spring的各个模块,从IoC容器到AOP,从MVC到Data访问,再到Boot的自动化配置。通过对源码的深度探索,你将能够更好地理解和利用Spring框架,提升自己的开发技能。
《Spring框架源码分析——基于UML图的解读》 在深入探讨Spring框架源码之前,我们首先要理解什么是UML(统一建模语言)。UML是一种标准的图形化建模语言,用于软件设计和系统分析,它通过图表来表示系统的结构、...
7. **源码分析** 对于深入理解Spring Security的工作原理,查看源码是十分有帮助的。例如,`AccessDecisionManager`的实现类,如`AffirmativeBased`和`UnanimousBased`,以及`AccessDecisionVoter`接口,它们共同...
在本篇博文中,我们将深入探讨Spring AOP(面向切面编程)中的一个重要概念——AfterReturning通知,这是Spring框架提供的一种强大的功能,允许我们在方法成功执行并返回后执行额外的操作。我们将通过源码分析和实际...
6. **Spring源码分析**:通过阅读源码,理解Spring框架的工作原理,增强对框架的深入理解。 接下来,我们转向MyBatis,这是一个轻量级的持久层框架,它提供了灵活的SQL映射机制,使得数据库操作变得简单。"MyBatis3...