问题导读

  • spring AOP是在如何进行的
  • spring 用cglib和jdkProxy管理的事务有何区别

Spring AOP管理

Spring主要的两个核心功能IOC与AOP。IOC的代码解析可以参照这里。

在IOC过程中会调用AbstractAutowireCapableBeanFactory.initializeBean初始化对象并将对象放入Spring容器

在这个方法中,等实例创建好会调用

wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

来包装生成的bean(这时还没有进行AOP)在这个方法中会调用wrapIfNecessary来进行包装

	//InfrastructureAdvisorAutoProxyCreator.class
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...
// 这里会获得响应的Advisor 其中就包含通过注解注释的@Transactional
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//这里就是开始创建proxy
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

在上面的createProxy其实会调用到ProxyFactory的getProxy方法

	//ProxyFactory.class
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
} public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//检查proxy_target_class标志和是否有接口
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface()) {
//如果类本生是接口则使用JDKProxy
return new JdkDynamicAopProxy(config);
}
//如果无接口或ProxyTargetClass为true使用CGLib
return CglibProxyFactory.createCglibProxy(config);
}
else {
//无ProxyTargetClass或且有接口使用JDK
return new JdkDynamicAopProxy(config);
}
}

上面的代码的就是Spring判断使用的JDK还是CGlib的情况

cglib代理模式

下面看下cglib的实现

在上面的getProxy方法中,Spring或默认注册几个默认的Callback(其中一个是DynamicAdvisedInterceptor他包含负责调用TransactionInterceptor也就是负责管理事务的Interceptor),这些Intercepter的构造函数如下

	private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

		private AdvisedSupport advised;

		public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}

在构造方法中都会传入一个advised变量,其实这个变量内部包含了在之前IOC过程中创建的那个原对象。

事务调用

当运行到需要事务管理的类时,以上所说的Interceptor将会进行拦截注入代码并invoke原本的对象

CglibAopProxy$CglibMethodInvocation.invokeJoinpoint()

                //CglibAopProxy$CglibMethodInvocation.invokeJoinpoint()
//获得上文所述advised对象中包含的原对象
protected Object getTarget() throws Exception {
return this.advised.getTargetSource().getTarget();
} //invoke原方法
protected Object invokeJoinpoint() throws Throwable {
if (this.protectedMethod) {
return super.invokeJoinpoint();
}
else {
return this.methodProxy.invoke(this.target, this.arguments);
}
}

在这里invoke时是调用的IOC阶段创立的bean而并非cglib自动创建的bean,其实这个时候如果使用visualVM等内存dump工具会看到内存中有两个对象(一个是IOC时创建的,一个是cglib create时创建的)。

在这里Spring AOP过程中使用的的是代理模式(就算使用的是CGLIB),这也就是为什么在使用Transaction注解时,如果调用自己的另一个Transactional的方法时,这个Transactional将不会起作用。

@Service
public class Test(){ public void fun1(){
fun2()
} @Transactional
public void fun2(){ }
}

以上如果调用fun1运行时fun2并不会被注入事务。

有几个解决办法

1.将自己注入进自己的一个变量,调用使用这个注入的变量,但是需要注意Transactional只支持在public方法中适用

2.使用AspectJ注入(mode="aspectj")

小结

本文主要简介了Transactional的注入过程,以及注意事项。

Spring Trasnaction管理(2)- 事务AOP的更多相关文章

  1. Spring Trasnaction管理(3)- 事务嵌套

    问题导读 Spring 如何管理嵌套的事务 Spring事务传播机制 Nested 和 RequireNew 有何区别 事务传播机制 事务的传播机制应该都比较熟悉 在日常开发中会遇到需要事务嵌套的情况 ...

  2. Spring Trasnaction管理(1)- 线程间事务隔离

    问题导读 Spring中事务是如何实现的 Spring中各个线程间是如何进行连接.事务隔离的 Spring事务配置 Spring的事务管理应该是日常开发中总会碰到的,但是Spring具体是怎么实现线程 ...

  3. Spring管理Hibernate事务

    在没有加入Spring来管理Hibernate事务之前,Hibernate对事务的管理的顺序是: 开始事务 提交事务 关闭事务 这样做的原因是Hibernate对事务默认是手动提交,如果不想手动提交, ...

  4. spring管理的事务

    之前对spring的事务传播机制没有概念,花点时间去看了事务的源码,以及这些事务传播机制使用的文档,在此做一下简单的笔记 正文 下面说提到的共享事务的意思就是几个service共用同一个事务,如传播机 ...

  5. spring的基于xml的AOP配置案例和切入点表达式的一些写法

    <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...

  6. Spring声明式事务管理基于tx/aop命名空间

    目的:通过Spring AOP 实现Spring声明式事务管理; Spring支持编程式事务管理和声明式事务管理两种方式. 而声明式事务管理也有两种常用的方式,一种是基于tx/aop命名空间的xml配 ...

  7. spring事务管理方式,aop

    达内12 note unit 09 01 1.spring事务管理 2.spring提供了对事务管理支持 spring采用aop机制完成事务控制 可以实现在不修改原有组件代码情况下实现事务控制功能. ...

  8. 全面分析 Spring 的编程式事务管理及声明式事务管理

    开始之前 关于本教程 本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本 ...

  9. Spring管理 hibernate 事务配置的五种方式

    Spring配置文件中关于事务配置总是由三个组成部分,DataSource.TransactionManager和代理机制这三部分,无论是那种配置方法,一般变化的只是代理机制这块! 首先我创建了两个类 ...

随机推荐

  1. Win10上使用SVN遇到的一些问题

    最近使用上了Win10,遇到了很多问题,前一段时间是MVC3项目的问题,今天又遇到了SVN工具使用的相关问题.我这个环境是WIN 10,64位,SVN工具是TortoiseSVN-1.9.2.2680 ...

  2. 类Collections的静态方法

    类Collections的静态方法 此类完全由在 collection 上进行操作或返回 collection 的静态方法组成. 排序 static <T extends Comparable& ...

  3. C++面试中关于sizeof问题总结

    原文:http://blog.sina.com.cn/s/blog_7c983ca60100yfdv.html#SinaEditor_Temp_FontName (1)      sizeof是操作符 ...

  4. 【转】mac os 安装php

    安装PHP 添加brew的PHP扩展库: brew update brew tap homebrew/dupes brew tap josegonzalez/homebrew-php 可以使用brew ...

  5. 解决拖拽有内容的div的bug和兼容问题

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 31.0px Consolas; color: #2b7ec3 } p.p2 { margin: 0.0px ...

  6. css3 自定义动画(1)

    <style> /*@-webkit-keyframes 动画名称 {} 用时:-webkit-animation:时间 动画名称; */ /* @-webkit-keyframes mo ...

  7. 黑马程序员-nil Nil NULL NSNull 野指针和空指针

    空指针1.空指针指不含有任何内存地址的指针.在没有具体初始化之前,其被符值为0Dog * dog = nil;Dog * dog = NULL;都为空指针2.野指针指指向的内存为垃圾内存,导致其值不确 ...

  8. 关于H5本部缓存localStorage,sessionStorage

    HTML5 提供了两种在客户端存储数据的新方法: localStorage - 没有时间限制的数据存储 sessionStorage - 针对一个 session 的数据存储 之前,这些都是由 coo ...

  9. How to create Web Deployment Package and install the package

    Create Web Deployment Package To configure settings on the Connection tab In the Publish method drop ...

  10. 如何参与Linux内核开发(转)

    本文来源于linux内核代码的Document文件夹下的Hoto文件.Chinese translated version of Documentation/HOWTO If you have any ...