`
风过无声
  • 浏览: 88347 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Spring AOP自调用

 
阅读更多

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/

分享到:
评论

相关推荐

    SpringAOP之探秘(动态代理、责任链模式、注解使用)

    SpringAOP之探秘(动态代理、责任链模式、注解使用)- 详情:https://blog.csdn.net/Dream_Weave/article/details/85008674

    spring aop之链式调用的实现

    主要介绍了spring aop之链式调用的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    Spring AOP实验

    1、按图所示的类图结构,设计接口及其实现类,并完成另外两附加要求:(1)日志功能:在程序执行期间追踪正在发生的活动(打印出调用的方法,以及参数的参数值);(2)验证功能:希望计算器只能处理正数的运算,当...

    SpringBean 调用 事务 AOP

    Spring,Bean调用,事务,AOP,配置详细说明 提升开发效率

    本地调用AOP

    spring的简化aop,前置通知,后置通知的简写

    Spring  AOP实现方法大全

    顾名思义,Before Advice会在目标对象的方法执行之前被调用,您可以通过实现org.springframework.aop.MethodBeforeAdvice接口来实现Before Advice的逻辑,接口定义如下: java 代码 1. package org.springframework....

    spring4 AOP 源代码

    基于spring4实现的AOP源代码。此源代码解压即用。

    spring-IOC-AOP调用大致过程(源码分析)

    spring version: 5.0.0; jdk: 1.8 IOC大致调用顺序(IOC调用的AOP标签解析)

    Spring_ch01-2.zip_springAOP

    Spring AOP创建BeforeAdvice和AfterAdvice实例 在对象被调用前后执行方法

    spring aop 实现源代码--xml and annotation(带lib包)

    顾名思义,Before Advice会在目标对象的方法执行之前被调用,您可以通过实现org.springframework.aop.MethodBeforeAdvice接口来实现Before Advice的逻辑,接口定义如下: java 代码 1. package org.spring...

    spring源码分析(1-10)

    Spring源代码解析(七):Spring AOP中对拦截器调用的实现 Spring源代码解析(八):Spring驱动Hibernate的实现 Spring源代码解析(九):Spring Acegi框架鉴权的实现 Spring源代码解析(十):Spring Acegi框架授权...

    Spring AOP配置源码

    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"&gt; &lt;context:component-scan base-package="com.spring.*"/&gt; &lt;aop:config&gt; &lt;aop:aspect id="aspect" ref="logIntercepter"&gt; &lt;aop:pointcut ...

    Spring-AOP.rar_spring aop 日志

    AOP技术则是将日志记录和安全检测代码封装为方法,在处理业务逻辑之前分别调用已经封装好的方法即可,有效解决重复性代码的问题,并为程序开发、调试带来极大方便

    Spring源代码解析(七):Spring_AOP中对拦截器调用的实现.doc

    Spring源代码解析(七):Spring_AOP中对拦截器调用的实现.doc

    Spring AOP详细介绍.docx

    一 AOP的基本概念 (1)Aspect(切面):通常是一个类,里面可以定义切入点和通知 (2)JointPoint(连接点):程序执行过程中明确的点,...Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

    Spring AOP 原理剖析,这一篇就够

    Spring AOP 学习记录 AOP(面向切面编程)方面的知识又是看了忘忘了看,今天有空记录下AOP的知识点。主要分为以下几方面: ​ 1、AOP相关术语 ​ 2、基础知识及示例 ​ 3、增强分类 1、AOP相关术语 连接点...

    Spring AOP 自动代理源码 DefaultAdvisorAutoProxyCreator

    Spring AOP源码04:MethodInvocation 拦截器调用 Spring AOP源码05:DefaultAdvisorAutoProxyCreator Spring期末考压轴题:当Spring AOP遇上循环依赖 git注释源码地址:...

    关于Spring AOP,除了动态代理、CGLIB,你还知道什么?

    Spring 作为 Java 中最流行的框架,主要归功于其提供的 IOC 和 AOP 功能。本文将讨论 Spring AOP 的实现。第一节将介绍 AOP 的相关概念,若熟悉可跳过,第二节中结合源码介绍 Spring 是如何实现 AOP 的各概念。 1. ...

    spring AOP拦截方法小示例

    用spring写的小示例程序,拦截某一层的所有方法。可以在调用之前、之后、抛出异常拦截调用,日志打印。

    Java八股文-Spring AOP

    切点用于来限定Spring-AOP启动的范围,通常我们采用表达式的方式来设置,所以关键词 是范围 通知(Advice) 通知是织入到目标类连接点上的一段程序代码。在Spring中,像 BeforeAdvice等还带有方位信息 通知是直译...

Global site tag (gtag.js) - Google Analytics