1.问题描述
目标对象内部的函数自我调用时被调函数将忽略切面。
1)实例
SelfInvokable.java
public interface SelfInvokable { void invoke(); void method(); }
SelfInvoker.java
public class SelfInvoker implements SelfInvokable { public void invoke() { System.out.println("in SelfInvoker.invoke..."); } public void method() { System.out.println("in SelfInvoker.method..."); this.invoke(); } }
SelfInvoker2.java
public class SelfInvoker2 { public void invoke() { System.out.println("in SelfInvoker2.invoke..."); } public void method() { System.out.println("in SelfInvoker2.method..."); this.invoke(); } }
spring-aop.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" 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="selfInvoker" class="com.siyuan.study.spring.aop.SelfInvoker"/> <bean id="selfInvoker2" class="com.siyuan.study.spring.aop.SelfInvoker2"/> <bean id="beforeAdvisor" class="com.siyuan.study.spring.aop.advisor.BeforeAdvisor"/> <aop:config> <aop:pointcut id="selfInvokerPointcut" expression="execution(* com.siyuan.study.spring.aop.*.*(..))" /> <aop:advisor advice-ref="beforeAdvisor" pointcut-ref="selfInvokerPointcut"/> </aop:config> </beans>
SelfInvokerAOPTest.java
public class SelfInvokerAOPTest { private ApplicationContext ctxt; @Before public void setup() { ctxt = new ClassPathXmlApplicationContext("spring-aop.xml"); } @Test public void testSelfInvokable() { SelfInvokable selfInvoker = (SelfInvokable) ctxt.getBean("selfInvoker"); System.out.println("JDK proxy : " + AopUtils.isJdkDynamicProxy(selfInvoker)); selfInvoker.invoke(); selfInvoker.method(); } @Test public void testSelfInvokable2() { SelfInvoker2 selfInvoker2 = (SelfInvoker2) ctxt.getBean("selfInvoker2"); System.out.println("CGLIB proxy : " + AopUtils.isCglibProxy(selfInvoker2)); selfInvoker2.invoke(); selfInvoker2.method(); } }
执行结果:
JDK proxy : true before invoke in SelfInvoker.invoke... before method in SelfInvoker.method... in SelfInvoker.invoke... CGLIB proxy : true before invoke in SelfInvoker2.invoke... before method in SelfInvoker2.method... in SelfInvoker2.invoke...
2)分析:
Spring AOP实现代理有两种方式
--JDK:目标对象有实现接口时,仅对目标对象实现接口中的方法进行拦截,接口中未包含的方法将不进行拦截。
--CGLIB:目标对象未实现任何接口时。
从执行结果来可看出,两种不同方式获得的代理在函数自我调用时被调用函数均忽略了切面。
2.修复
1)AopContext获取代理对象,实现原理ThreadLocal
SelfInvokable.java
public interface SelfInvokable { ... void methodFix(); }
SelfInvoker.java
public class SelfInvoker implements SelfInvokable { ... public void methodFix() { System.out.println("in SelfInvoker.methodFix..."); ((SelfInvokable) AopContext.currentProxy()).invoke(); } }
SelfInvoker2.java
public class SelfInvoker2 { ... public void methodFix() { System.out.println("in SelfInvoker2.methodFix..."); ((SelfInvoker2) AopContext.currentProxy()).invoke(); } }
spring-aop.xml
... <aop:config expose-proxy="true"> ...
SelfInvokerAOPTest.java
@Test public void testSelfInvokable() { ... selfInvoker.methodFix(); } @Test public void testSelfInvokable2() { ... selfInvoker2.methodFix(); }
执行结果
JDK proxy : true before invoke in SelfInvoker.invoke... before method in SelfInvoker.method... in SelfInvoker.invoke... before methodFix in SelfInvoker.methodFix... before invoke in SelfInvoker.invoke... CGLIB proxy : true before invoke in SelfInvoker2.invoke... before method in SelfInvoker2.method... in SelfInvoker2.invoke... before methodFix in SelfInvoker2.methodFix... before invoke in SelfInvoker2.invoke...
2)BeanPostProcessor+BeanSelfAware(标记需要自调用的接口)
BeanSelfAware.java
public interface BeanSelfAware { void setSelf(Object self); }
SelfInvoker.java
... public void methodFix() { System.out.println("in SelfInvoker.methodFix..."); //((SelfInvokable) AopContext.currentProxy()).invoke(); self.invoke(); } private SelfInvokable self; public void setSelf(Object self) { this.self = (SelfInvokable) self; } ...
InjectBeanSelfProcessor.java
public class InjectBeanSelfProcessor implements BeanPostProcessor { public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(bean instanceof BeanSelfAware) { BeanSelfAware myBean = (BeanSelfAware)bean; myBean.setSelf(bean); return myBean; } return bean; } public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } }
spring-aop.xml
... <bean class="com.siyuan.study.spring.extension.InjectBeanSelfProcessor"/> ...
SelfInvokerAOPTest.java
... @Test public void testSelfInvokable() { SelfInvokable selfInvoker = (SelfInvokable) ctxt.getBean("selfInvoker"); //System.out.println("JDK proxy : " + AopUtils.isJdkDynamicProxy(selfInvoker)); //selfInvoker.invoke(); //selfInvoker.method(); selfInvoker.methodFix(); } ...
运行结果
before setSelf before methodFix in SelfInvoker.methodFix... before invoke in SelfInvoker.invoke... before setSelf
3.参考资料
http://blog.163.com/yf_198407/blog/static/513854112012621105114276/
相关推荐
Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的重要组成部分,它提供了一种在不修改源代码的情况下,对程序进行功能增强的技术。这个"spring aop jar 包"包含了实现这一功能所需的类和接口,...
Spring AOP(面向切面编程)是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`:...
Spring AOP 是一种面向切面编程的技术,它允许我们在不修改源代码的情况下,对应用程序的特定部分(如方法调用)进行增强。在 Spring 中,AOP 的实现主要依赖于代理模式,有两种代理方式:JDK 动态代理和 CGLIB 动态...
在Spring AOP中,我们无需深入到每个方法的实现细节,而是可以定义“切面”,在合适的时机(如方法调用前、后、异常发生时等)执行特定的逻辑。这样,业务代码和关注点(如日志、事务管理等)得以分离,提高了代码的...
Spring AOP主要支持方法调用作为连接点。 3. **通知(Advice)**:在特定的连接点处执行的动作,如before通知(在连接点之前执行),after通知(在连接点之后执行),around通知(环绕连接点执行)等。通知是AOP中...
**Spring AOP 实现机制详解** Spring AOP(面向切面编程)是Spring框架的核心特性之一,它允许程序员在不修改源代码的情况下,通过“切面”来插入额外的业务逻辑,如日志、事务管理等。AOP的引入极大地提高了代码的...
动态代理是实现AOP的一种常用技术,它允许在运行时创建代理对象,拦截对真实对象的调用,并在调用前后添加额外的行为。 在Java开发中,反射机制是实现动态代理的关键技术之一。反射提供了在运行时访问和操作类的...
Spring AOP 是Spring框架提供的一个功能模块,它允许开发者将横切关注点(cross-cutting concerns)从业务逻辑中解耦出来,通过在方法调用前后进行拦截来实现。这些横切关注点通常是一些与业务逻辑不直接相关的服务...
5. **代理(Proxy)**:Spring AOP通过动态代理机制创建目标对象的代理,代理对象在调用目标方法时会自动插入切面逻辑。在Java项目中,Spring可以使用JDK动态代理或CGLIB动态代理来创建代理对象。 在实际应用中,...
Spring AOP(面向切面编程)是Spring框架的重要组成部分,它提供了一种模块化和抽象化的方法来处理系统中的交叉关注点,如日志、事务管理、安全性等。本学习笔记将深入探讨Spring AOP的核心概念、工作原理以及实际...
5. **代理(Proxy)**:Spring AOP通过动态代理机制创建目标对象的代理,代理对象负责拦截方法调用并执行通知。有两种代理类型:JDK动态代理和CGLIB代理。JDK代理用于实现了接口的目标对象,而CGLIB代理则用于没有...
Spring AOP(面向切面编程)是Spring框架的重要组成部分,它提供了一种模块化和声明式的方式来处理系统中的交叉关注点,如日志、事务管理、性能监控等。在使用Spring AOP时,通常需要引入特定的jar包来支持其功能。...
在IT领域,Spring框架是一个广泛使用的Java应用框架,它提供了许多功能,包括依赖注入、面向切面编程(AOP)等。"spring-aop-jar"这个主题涉及到Spring框架中的核心组件之一——Spring AOP。这里我们将深入探讨...
**Spring AOP 配置实现详解** Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的重要组成部分,它允许我们通过分离关注点来简化应用程序的开发。在传统的面向对象编程中,业务逻辑与日志记录...
**Spring AOP 简介** Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的一个重要模块,它扩展了传统的面向对象编程,允许开发者定义“横切关注点”(cross-cutting concerns),如日志、事务...
Spring AOP,全称Aspect-Oriented Programming(面向切面编程),是Spring框架的重要组成部分,它为Java应用程序提供了声明式的企业级服务,如事务管理、日志记录等。AOP的核心概念是切面(Aspect)和通知(Advice)...
在Spring AOP中,代理是实现切面的关键机制,它在目标对象与实际调用之间起到了中介作用,让我们来详细探讨Spring AOP的默认代理方式。 1. **静态代理**:Spring AOP 提供了两种代理方式,一种是静态代理,另一种是...
Spring AOP(面向切面编程)是Spring框架的重要组成部分,它允许程序员在不修改源代码的情况下,对应用程序的特定部分(如方法调用)进行拦截和处理。这为日志、事务管理、性能监控等提供了方便。本示例提供了一种...