问题导读

  • 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. 16条Web2.0法则的编程思想

    1.在你开始之前,先定一个简单的目标.无论你是一个Web 2.0应用的创建者还是用户,请清晰的构思你的目标.就像“我需要保存一个书签”或者“我准 备帮助人们创建可编辑的.共享的页面”这样的目标,让你保 ...

  2. (转)C语言16进制输出字符型变量问题

    最近在做一个C的嵌入式项目,发现在C语言中用printf()函数打印字符型变量时,如果想采用"%x"的格式将字符型变量值以十六进制形式打印出来,会出现一个小问题,如下: char  ...

  3. Java 下的 JSON库性能比较:JSON.simple

    JSON已经成为当前服务器与WEB应用之间数据传输的公认标准,不过正如许多我们所习以为常的事情一样,你会觉得这是理所当然的便不再深入思考了.我们很少会去想用到的这些JSON库到底有什么不同,但事实上它 ...

  4. Python垃圾回收机制

    引用计数Python默认的垃圾收集机制是“引用计数”,每个对象维护了一个ob_ref字段.它的优点是机制简单,当新的引用指向该对象时,引用计数 引用计数 Python默认的垃圾收集机制是“引用计数”, ...

  5. AutoVue ISDK学习总结(一)

    这段时间,断断续续花了2,3周时间,研究AutoVue ISDK.貌似这个东西用的人很少,网上只搜到了一篇中文文档.自己英文水平差,Java水平也差,看Oracle官网文档,进展非常慢.到现在,终于对 ...

  6. ruby使用DBI连接MySQL数据库发生异常:in `error': Can't connect to MySQL server on 'localhost' (10061) (DBI::DatabaseError)

    Ruby使用DBI连接MySQL数据库一般为: require "dbi" dbh = DBI.connect("dbi:Mysql:test:localhost&quo ...

  7. selenium support

      org.openqa.selenium.support.ui.Select select = new org.openqa.selenium.support.ui.Select(driver.fi ...

  8. Eclipse 包排版问题

    问题描述: 在Eclipse中,项目结构如下所示: 这样的显示方式,查找内容太不方便.使用不习惯. 解决方法: Eclipse中默认包的显示方式为flat,使其改为Hierarchical. 操作步骤 ...

  9. wpf下datagrid使用过程中需要注意的几点(一)

    MainWindow.xaml中的代码如下: <DataGrid CanUserAddRows="False" ItemsSource="{Binding}&quo ...

  10. 高性能网站架构设计之缓存篇(2)- Redis C#客户端

    在上一篇中我简单的介绍了如何利用redis自带的客户端连接server并执行命令来操作它,但是如何在我们做的项目或产品中操作这个强大的内存数据库呢?首先我们来了解一下redis的原理吧. 官方文档上是 ...