一、AOP是Aspect Oriented Programing 的简称,面向方面(切面)编程。
(1)、AOP的应用场合:适用于那些具有横切逻辑的应用场合,如:性能检测、访问控制、事务管理以及日志记录。
(2)、面向切面编程的概念:假设我们将ForumService业务类看成一段圆木,将removeTopic()方法和createForum()方法看成圆木的一截,我们会发现性能检测和事务管理的代码就好像一个年轮,而业务代码就是圆木的树心,这也正是横切代码概念的又来。而AOP希望将这些分散的各个业务逻辑代码中的相同代码,通过横向切割的方式抽取到一个独立的模块中,
还业务逻辑一个清新的世界。当让,我们知道将这些重复的横切逻辑独立出来很容易,但如何将这些独立的逻辑融合到业务逻辑中完成和原来一样的业务操作,这才是事情的关键,也正式AOP要解决的主要问题。
(3)、AOP术语
1、连接点(joinPoint)和切点(pointCut):每个程序类都拥有多个连接点,如一个拥有两个方法的类,这两个方法都是连接点,即连接点是程序类中客观存在的事务。但在这为数众多的连接点中,如何定位到敢兴趣的连接点呢?AOP通过"切点(pointCut)"定位特定连接点。通过数据库查询的概念来理解切点和连接点的关系再合适不过了;连接点相当于数据库中的记录,而切点相当于查询条件。切点和连接点不是一对一的关系,一个切点可以匹配多个连接点。
2、增强(Advince):是织入到目标类连接点上的一段程序代码。
3、目标对象(Target):增强逻辑织入的目标类。
4、织入(weaving):织入是将增强添加对目标类具体连接点的过程。AOP就想一台织布机,将目标类、增强或者引介通过AOP这台织布机天衣无缝的编织在一起。
根据不同的织入技术,AOP有三种织入方式:
1)、编译期织入,这要求使用特殊的Java编译器。
2)、类装载期织入,这要求使用特殊的类装载器。
3)、动态代理织入,在运行期为目标类添加增强生成子类的方式。
5、代理(Proxy):一个类被AOP织入增强以后,就产生了一个结果类,它是融合了源类和增强逻辑的代理类。根据不同的代理方式,代理类既可能是和原类具有相同
接口的类,也可能是原来类的子类,所以我们可以采用调用原来类相同的方式调用代理类。
6、切面(Aspect):切面是由切点和增强(引介)组成的,它既包含了横切逻辑的定义,也包括了连接点的定义,SpringAOP就是负责实施切面的框架,它将切面所定义的横切逻辑织入到切面所指定的连接点中。
(4)、AOP的工作重心:如何将增强应用于目标连接点上,这是首先包括两个工作:第一,如何通过切点和增强定位到连接点上;第二:如何在增强中编写切面的代码。
(5)、AOP的实现原理:Spring AOP使用动态代理技术在运行期间织入增强的代码,Spring AOP使用两种代理机制;一种是基于Jdk的动态代理;另一种是基于CGlib的动态代理,很大程度上JDK本身只提供接口的代理,而不支持类的代理。
二、简单的示例:
- package com.yt.spring.user;
- /**
- * @Description:定义接口类
- * @ClassName: IUserBean
- * @Project: spring-aop
- * @Author: zxf
- * @Date: 2011-5-23
- */
- public interface IUserBean {
- public UserBean getUser(String userId);
- public int deleteUser(String userId);
- public void insertUser(UserBean user);
- }
package com.yt.spring.user; /** * @Description:定义接口类 * @ClassName: IUserBean * @Project: spring-aop * @Author: zxf * @Date: 2011-5-23 */ public interface IUserBean { public UserBean getUser(String userId); public int deleteUser(String userId); public void insertUser(UserBean user); }
- package com.yt.spring.user;
- import org.apache.log4j.Logger;
- /**
- * @Description: 实现类
- * @ClassName: UserBeanImpl
- * @Project: spring-aop
- * @Author: zxf
- * @Date: 2011-5-23
- */
- public class UserBeanImpl implements IUserBean {
- Logger log = Logger.getLogger(UserBeanImpl.class);
- @Override
- public UserBean getUser(String userId) {
- log.info("查找用户..............");
- return null;
- }
- @Override
- public int deleteUser(String userId) {
- log.info("删除用户.............." + userId);
- return 100;
- }
- @Override
- public void insertUser(UserBean user) {
- log.info("添加用户..............");
- }
- }
package com.yt.spring.user; import org.apache.log4j.Logger; /** * @Description: 实现类 * @ClassName: UserBeanImpl * @Project: spring-aop * @Author: zxf * @Date: 2011-5-23 */ public class UserBeanImpl implements IUserBean { Logger log = Logger.getLogger(UserBeanImpl.class); @Override public UserBean getUser(String userId) { log.info("查找用户.............."); return null; } @Override public int deleteUser(String userId) { log.info("删除用户.............." + userId); return 100; } @Override public void insertUser(UserBean user) { log.info("添加用户.............."); } }
- package com.yt.spring.user;
- /**
- * @Description: 实体类
- * @ClassName: UserBean
- * @Project: spring-aop
- * @Author: zxf
- * @Date: 2011-5-23
- */
- public class UserBean {
- public String userId;
- public String userName;
- public String userAddress;
- public String getUserId() {
- return userId;
- }
- public void setUserId(String userId) {
- this.userId = userId;
- }
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- public String getUserAddress() {
- return userAddress;
- }
- public void setUserAddress(String userAddress) {
- this.userAddress = userAddress;
- }
- }
package com.yt.spring.user; /** * @Description: 实体类 * @ClassName: UserBean * @Project: spring-aop * @Author: zxf * @Date: 2011-5-23 */ public class UserBean { public String userId; public String userName; public String userAddress; public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserAddress() { return userAddress; } public void setUserAddress(String userAddress) { this.userAddress = userAddress; } }
(1)、使用注解的方式来声明代理类
- package com.yt.spring;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.After;
- import org.aspectj.lang.annotation.AfterReturning;
- 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;
- /**
- * @Description: 使用注解的方式来声明切面类
- * @ClassName: MyInterceptor
- * @Project: spring-aop
- * @Author: zxf
- * @Date: 2011-5-23
- */
- @Aspect
- public class MyInterceptor {
- /**
- * 定义切入点
- * 第一个*表示方法的返回值,这里使用通配符,只有返回值符合条件的才拦截,(!void表示有返回值)
- * 第一个..表示com.royzhou.aop包及其子包
- * 倒数第二个*表示包下的所有Java类都被拦截
- * 最后一个*表示类的所有方法都被拦截
- * (..)表示方法的参数可以任意多个如[(java.lang.String,java.lang.Integer)表示第一个参数是String,
- * 第二个参数是int的方法才会被拦截]
- */
- @SuppressWarnings("unused")
- @Pointcut("execution(* com.yt.spring.user.*.*(..))")
- private void pointCutMethod() {
- }
- // 定义置前通知
- @Before("pointCutMethod()&&args(userId)")
- public void doBefore(String userId) {
- System.out.println("定义前置通知.........方法获取参数:" + userId);
- }
- // 定义后置通知
- @AfterReturning(pointcut = "pointCutMethod()", returning = "result")
- public void doAfterReturning(int result) {
- System.out.println("定义置后通知.........方法返回值:" + result);
- }
- // 定义例外通知
- @AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
- public void doAfterException(String e) {
- System.out.println("定义例外通知.........出现异常:" + e);
- }
- // 定义最终通知
- @After("pointCutMethod()")
- public void doAfter() {
- System.out.println("定义最终通知.........");
- }
- // 定义环绕通知
- @Around("pointCutMethod()")
- public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
- System.out.println("进入方法");
- Object object = pjp.proceed(); // 必须执行pjp.proceed()方法,如果不执行此方法,业务bean的方法以及后续通知都不执行
- System.out.println("退出方法");
- return object;
- }
- }
package com.yt.spring; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; 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; /** * @Description: 使用注解的方式来声明切面类 * @ClassName: MyInterceptor * @Project: spring-aop * @Author: zxf * @Date: 2011-5-23 */ @Aspect public class MyInterceptor { /** * 定义切入点 * 第一个*表示方法的返回值,这里使用通配符,只有返回值符合条件的才拦截,(!void表示有返回值) * 第一个..表示com.royzhou.aop包及其子包 * 倒数第二个*表示包下的所有Java类都被拦截 * 最后一个*表示类的所有方法都被拦截 * (..)表示方法的参数可以任意多个如[(java.lang.String,java.lang.Integer)表示第一个参数是String, * 第二个参数是int的方法才会被拦截] */ @SuppressWarnings("unused") @Pointcut("execution(* com.yt.spring.user.*.*(..))") private void pointCutMethod() { } // 定义置前通知 @Before("pointCutMethod()&&args(userId)") public void doBefore(String userId) { System.out.println("定义前置通知.........方法获取参数:" + userId); } // 定义后置通知 @AfterReturning(pointcut = "pointCutMethod()", returning = "result") public void doAfterReturning(int result) { System.out.println("定义置后通知.........方法返回值:" + result); } // 定义例外通知 @AfterThrowing(pointcut = "pointCutMethod()", throwing = "e") public void doAfterException(String e) { System.out.println("定义例外通知.........出现异常:" + e); } // 定义最终通知 @After("pointCutMethod()") public void doAfter() { System.out.println("定义最终通知........."); } // 定义环绕通知 @Around("pointCutMethod()") public Object doAround(ProceedingJoinPoint pjp) throws Throwable { System.out.println("进入方法"); Object object = pjp.proceed(); // 必须执行pjp.proceed()方法,如果不执行此方法,业务bean的方法以及后续通知都不执行 System.out.println("退出方法"); return object; } }
对应的applicationContext.xml配置
- <?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"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:jee="http://www.springframework.org/schema/jee"
- xmlns:jms="http://www.springframework.org/schema/jms"
- xmlns:lang="http://www.springframework.org/schema/lang"
- xmlns:p="http://www.springframework.org/schema/p"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:util="http://www.springframework.org/schema/util"
- xmlns:ehcache="http://www.springmodules.org/schema/ehcache"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
- http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd
- http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
- http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
- http://www.springmodules.org/schema/ehcache http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd">
- <!-- 打开aspectj注解处理器,proxy-target-class="true"表示使用CGlib实现类代理-->
- <aop:aspectj-autoproxy proxy-target-class="true"/>
- <!-- 配置切面bean -->
- <bean id="MyInterceptor" class="com.yt.spring.MyInterceptor"></bean>
- <bean id="userBean" class="com.yt.spring.user.UserBeanImpl"></bean>
- </beans>
<?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" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:jms="http://www.springframework.org/schema/jms" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xmlns:ehcache="http://www.springmodules.org/schema/ehcache" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springmodules.org/schema/ehcache http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd"> <!-- 打开aspectj注解处理器,proxy-target-class="true"表示使用CGlib实现类代理--> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 配置切面bean --> <bean id="MyInterceptor" class="com.yt.spring.MyInterceptor"></bean> <bean id="userBean" class="com.yt.spring.user.UserBeanImpl"></bean> </beans>
(二)、使用配置的方式来声明切面类
- package com.yt.spring;
- import org.aspectj.lang.ProceedingJoinPoint;
- /**
- * @Description: 使用xml配置的方式来声明切面类
- * @ClassName: MyInterceptor
- * @Project: spring-aop
- * @Author: zxf
- * @Date: 2011-5-23
- */
- public class MyInterceptorXml {
- // 定义置前通知
- public void doBefore(String userId) {
- System.out.println("定义前置通知.........方法获取参数:" + userId);
- }
- // 定义后置通知
- public void doAfterReturning(int result) {
- System.out.println("定义置后通知.........方法返回值:" + result);
- }
- // 定义例外通知
- public void doAfterException(String e) {
- System.out.println("定义例外通知.........出现异常:" + e);
- }
- // 定义最终通知
- public void doAfter() {
- System.out.println("定义最终通知.........");
- }
- // 定义环绕通知
- public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
- System.out.println("进入方法");
- Object object = pjp.proceed(); // 必须执行pjp.proceed()方法,如果不执行此方法,业务bean的方法以及后续通知都不执行
- System.out.println("退出方法");
- return object;
- }
- }
package com.yt.spring; import org.aspectj.lang.ProceedingJoinPoint; /** * @Description: 使用xml配置的方式来声明切面类 * @ClassName: MyInterceptor * @Project: spring-aop * @Author: zxf * @Date: 2011-5-23 */ public class MyInterceptorXml { // 定义置前通知 public void doBefore(String userId) { System.out.println("定义前置通知.........方法获取参数:" + userId); } // 定义后置通知 public void doAfterReturning(int result) { System.out.println("定义置后通知.........方法返回值:" + result); } // 定义例外通知 public void doAfterException(String e) { System.out.println("定义例外通知.........出现异常:" + e); } // 定义最终通知 public void doAfter() { System.out.println("定义最终通知........."); } // 定义环绕通知 public Object doAround(ProceedingJoinPoint pjp) throws Throwable { System.out.println("进入方法"); Object object = pjp.proceed(); // 必须执行pjp.proceed()方法,如果不执行此方法,业务bean的方法以及后续通知都不执行 System.out.println("退出方法"); return object; } }
applicationContext.xml对应的配置:
- <bean id="MyInterceptorXml" class="com.yt.spring.MyInterceptorXml"></bean>
- <aop:config>
- <aop:aspect id="asp" ref="MyInterceptorXml">
- <aop:pointcut id="mycut" expression="execution(* com.yt.spring.user.*.*(..))"/>
- <aop:before pointcut="execution(* com.yt.spring.user.*.*(..)) and args(userId)" method="doBefore"/>
- <aop:after-returning pointcut-ref="mycut" method="doAfterReturning" returning="result"/>
- <aop:after-throwing pointcut-ref="mycut" method="doAfterException" throwing="e"/>
- <aop:after pointcut-ref="mycut" method="doAfter"/>
- <aop:around pointcut-ref="mycut" method="doAround"/>
- </aop:aspect>
- </aop:config>
<bean id="MyInterceptorXml" class="com.yt.spring.MyInterceptorXml"></bean> <aop:config> <aop:aspect id="asp" ref="MyInterceptorXml"> <aop:pointcut id="mycut" expression="execution(* com.yt.spring.user.*.*(..))"/> <aop:before pointcut="execution(* com.yt.spring.user.*.*(..)) and args(userId)" method="doBefore"/> <aop:after-returning pointcut-ref="mycut" method="doAfterReturning" returning="result"/> <aop:after-throwing pointcut-ref="mycut" method="doAfterException" throwing="e"/> <aop:after pointcut-ref="mycut" method="doAfter"/> <aop:around pointcut-ref="mycut" method="doAround"/> </aop:aspect> </aop:config>
最后贴出测试类:
- package com.yt.spring;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- import com.yt.spring.user.IUserBean;
- /**
- * @Description:测试AOP
- * @ClassName: Test
- * @Project: spring-aop
- * @Author: zxf
- * @Date: 2011-5-23
- */
- public class Test {
- public static void main(String[] args) {
- ApplicationContext ctx = new ClassPathXmlApplicationContext(
- "applicationContext.xml");
- // 接口代理
- IUserBean userBean = (IUserBean) ctx.getBean("userBean");
- // UserBeanImpl userBean = (UserBeanImpl) ctx.getBean("userBean");
- userBean.deleteUser("419688091");
- }
- }
相关推荐
在讨论Spring AOP(面向切面编程)时,首先需要理解几个核心概念。Spring AOP 是Spring框架提供的一个功能模块,它允许开发者将横切关注点(cross-cutting concerns)从业务逻辑中解耦出来,通过在方法调用前后进行...
Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的重要组成部分,它提供了一种在不修改源代码的情况下,对程序进行功能增强的技术。AOP的核心概念是切面(Aspect)、通知(Advice)、连接点...
**Spring AOP编程实例** Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的核心特性之一,它提供了一种在不修改原有代码的情况下,通过插入额外的行为(如日志、事务管理等)来增强功能的...
【Spring AOP编程】是Java开发中的一个重要概念,它代表了面向切面编程(Aspect-Oriented Programming)在Spring框架中的应用。AOP的核心思想是将关注点分离,即将横切关注点(如日志、事务管理、安全性等)与核心...
### Spring AOP面向方面编程原理:AOP概念详解 #### 一、引言 随着软件系统的日益复杂,传统的面向对象编程(OOP)逐渐暴露出难以应对某些横切关注点(cross-cutting concerns)的问题。为了解决这一挑战,面向方面编程...
在Java开发领域,Spring框架是不可或缺的一部分,而Spring AOP(面向切面编程)则是Spring框架中的重要特性,它提供了一种优雅的方式来处理系统中的横切关注点,如日志、事务管理等。本篇文章将深入探讨如何通过XML...
在Java EE环境中,Spring框架是企业级应用开发的首选,其中Spring AOP(Aspect-Oriented Programming,面向切面编程)是其核心组件之一。面向切面编程是一种编程范式,旨在提高代码的可重用性和模块化,通过将关注点...
在本文档中,作者田超凡探讨了Spring AOP(面向切面编程)的实现,主要涉及了两种代理模式:静态代理和JDK动态代理。这两种代理方式都是为了实现AOP的核心理念,即在不修改原有业务代码的情况下,对代码进行横切关注...
### Spring AOP面向切面编程详解 #### 一、引言 面向切面编程(Aspect Oriented Programming,简称AOP)是一种编程范式,旨在提高软件的模块化程度,简化程序设计并解决横切关注点(Cross-cutting Concerns)的问题...
Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的重要组成部分,它提供了一种在不修改源代码的情况下,对程序进行功能增强的技术。这个"spring aop jar 包"包含了实现这一功能所需的类和接口,...
Spring AOP 编程 Spring AOP(Aspect-Oriented Programming,面向切面编程)是一种编程技术,它可以将横切关注点从核心业务逻辑中分离出来,提高系统的可维护性、可扩展性和灵活性。AOP 是 OOP 的补充和完善,可以...
在Java编程领域,Spring AOP(面向切面编程)是一种强大的设计模式,它允许程序员将关注点分离到单独的模块,这些模块可以独立于主业务逻辑进行管理。本教程将重点讲解如何通过注解方式来实现Spring AOP,并提供相关...
实战示例
Spring AOP,全称为Aspect Oriented Programming,是面向切面编程的一种编程范式,它是对传统的面向对象编程(OOP)的一种补充。在OOP中,核心是对象,而在AOP中,核心则是切面。切面是关注点的模块化,即程序中的...
Spring AOP(面向切面编程)是Spring框架的重要组成部分,它提供了一种模块化和声明式的方式来处理系统中的交叉关注点问题,如日志、事务管理、安全性等。本示例将简要介绍如何在Spring应用中实现AOP,通过实际的...
Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的重要组成部分,它扩展了传统的面向对象编程,使得开发者可以方便地实现横切关注点,如日志、事务管理、性能监控等。在Spring中,AOP通过代理...
Spring AOP(面向切面编程)是Spring框架的核心特性之一,它允许开发者在不修改源代码的情况下,通过插入切面来增强或改变程序的行为。在本教程中,我们将深入探讨Spring AOP的不同使用方法,包括定义切点、通知类型...
现在,我们回到主题——"springaop依赖的jar包"。在Spring 2.5.6版本中,使用Spring AOP通常需要以下核心jar包: - `spring-aop.jar`:这是Spring AOP的核心库,包含了AOP相关的类和接口。 - `spring-beans.jar`:...