1、定义接口和实现

public interface UserService {
public String getName(int id); public Integer getAge(int id);
}

 

public class UserServiceImpl implements UserService {
@Override
public String getName(int id) {
System.out.println("------getName------");
return "Tom";
} @Override
public Integer getAge(int id) {
System.out.println("------getAge------");
return 10;
}
}

  

 

2、jdk动态代理实现

BeanFactiory 创建注入方法时使用

               if (object.getClass().getPackage().getName().equals("")) {
ConnectionDynamicProxy connectionDynamicProxy = new ConnectionDynamicProxy();
connectionDynamicProxy.setTarget(object); //daili object
Object proxyObject = Proxy.newProxyInstance(object.getClass().getClassLoader(),
object.getClass().getInterfaces(), connectionDynamicProxy);
return proxyObject;
}

  

public class ConnectionDynamicProxy implements InvocationHandler{

    private Object target;

    public void setTarget(Object target) {
this.target = target;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
boolean needMyClose = false;
Connection conn = (Connection) AppContext.getAppContext().getObject("APP_REQUEST_THREAD_CONNECTION");
if (conn == null) {
conn = DBUtil.getConnection();
needMyClose = true;
AppContext.getAppContext().addObject("APP_REQUEST_THREAD_CONNECTION",conn);
}
try {
result = method.invoke(target, args);
} finally {
if (needMyClose) {
conn = (Connection) AppContext.getAppContext().getObject("APP_REQUEST_THREAD_CONNECTION");
DBUtil.close(conn, null, null);
AppContext.getAppContext().removeObject("APP_REQUEST_THREAD_CONNECTION");
conn = null;
}
}
return result;
} }

代理对象

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.sql.Connection; import com.augmentum.oes.util.DBUtil; public class ConnectionDynamicProxy implements InvocationHandler{ private Object target; public void setTarget(Object target) {
this.target = target;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
boolean needMyClose = false;
boolean isCommitOrRollbackTran = false;
ConnectionHolder connectionHolder = (ConnectionHolder) AppContext.getAppContext().getObject("APP_REQUEST_THREAD_CONNECTION"); if (connectionHolder == null) {
connectionHolder = new ConnectionHolder();
Connection conn = DBUtil.getConnection();
connectionHolder.setConn(conn);
if (method.getName().equals("add")) {
DBUtil.setAutoCommit(conn, false);
connectionHolder.setStartTran(true);
isCommitOrRollbackTran = true;
}
AppContext.getAppContext().addObject("APP_REQUEST_THREAD_CONNECTION",connectionHolder);
needMyClose = true;
} else {
if (method.getName().equals("add")) {
if(!connectionHolder.isStartTran()) {
connectionHolder.setStartTran(true);
DBUtil.setAutoCommit(connectionHolder.getConn() , false);
isCommitOrRollbackTran = true;
}
}
}
try {
result = method.invoke(target, args);
if (method.getName().equals("add")) {
if (isCommitOrRollbackTran) {
DBUtil.commit(connectionHolder.getConn());
} }
} catch (Throwable throwable) {
if (method.getName().equals("add")) {
if (isCommitOrRollbackTran) {
DBUtil.rollback(connectionHolder.getConn());
} }
throw throwable;
} finally {
if (needMyClose) {
connectionHolder = (ConnectionHolder) AppContext.getAppContext().getObject("APP_REQUEST_THREAD_CONNECTION");
DBUtil.close(connectionHolder.getConn(), null, null);
AppContext.getAppContext().removeObject("APP_REQUEST_THREAD_CONNECTION");
connectionHolder.setConn(null);
connectionHolder = null;
}
}
return result;
} }

 放置connection与是否开启事务

package com.augmentum.oes.common;

import java.sql.Connection;

public class ConnectionHolder {
private Connection conn;
private boolean isStartTran = false; public Connection getConn() {
return conn;
} public void setConn(Connection conn) {
this.conn = conn;
} public boolean isStartTran() {
return isStartTran;
} public void setStartTran(boolean isStartTran) {
this.isStartTran = isStartTran;
} }

ConnectionHolder

也就是说main函数里面的proxy实际就是$Proxy0的一个实例对象。
可知JDK动态代理是使用接口生成新的实现类,实现类里面则委托给InvocationHandler,InvocationHandler里面则调用被代理的类方法

 

3、cglib动态代理实现

Cglib是通过直接继承被代理类,并委托为回调函数来做具体的事情:

从代理类里面可知道对于原来的add函数,代理类里面对应了两个函数分布是add 和CGLIB$add$0
其中后者是在方法拦截器里面调用的的,前者则是我们使用代理类时候调用的函数。当我们代码调用add时候,会具体调用到方法拦截器的intercept方法,该方法内则通过proxy.invokeSuper调用CGLIB$add$0

这是一个需要被代理的类,也就是父类,通过字节码技术创建这个类的子类,实现动态代理。

public class SayHello {
public void say(){
System.out.println("hello everyone");
}
}

  

该类实现了创建子类的方法与代理的方法。getProxy(SuperClass.class)方法通过入参即父类的字节码,通过扩展父类的class来创建代理对象。intercept()方法拦截所有目标类方法的调用,obj表示目标类的实例,method为目标类方法的反射对象,args为方法的动态入参,proxy为代理类实例。proxy.invokeSuper(obj, args)通过代理类调用父类中的方法。

public class CglibProxy implements MethodInterceptor{
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
//设置需要创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
return enhancer.create();
}
//实现MethodInterceptor接口方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("前置代理");
//通过代理类调用父类中的方法
Object result = proxy.invokeSuper(obj, args);
System.out.println("后置代理");
return result;
}
}

  实现类

public class DoCGLib {
public static void main(String[] args) {
CglibProxy proxy = new CglibProxy();
//通过生成子类的方式创建代理类
SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class);
proxyImp.say();
}
}

 结果

前置代理
hello everyone
后置代理

  

 

关闭事务自动提交   
public static void setAutoCommit(Connection conn, boolean autoCommit) {
try {
conn.setAutoCommit(autoCommit);
} catch (SQLException e) {
e.printStackTrace();
throw new DBException();
}
} 同一事务代码块 提交事务 commit
catch 调用
public void rollback(Connection conn) {
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
throw new DBException();
}
}

  

 

 四 spring 进行 事务 管理

    <!-- add Transation Manger -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
<!-- start Transation annoation --> 加入这个时可以直接使用注解@Transctional
<tx:annotation-driven transaction-manager="transactionManager"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="update" propagation="REQUIRED" read-only="false"/>
<tx:method name="deleteById" propagation="REQUIRED" read-only="false"/>
<tx:method name="getNextId" propagation="REQUIRED" read-only="false"/>
<tx:method name="addUpdate" propagation="REQUIRED" read-only="false"/>
<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(* com.augmentum.oes.service..*.*(..))" id="pc"/>
<aop:advisor pointcut-ref="pc" advice-ref="txAdvice" order="1"/>
</aop:config>

rollbackFor  设置为此异常回滚。 大部分异常继承runtimeException

对应JDK动态代理机制是委托机制,具体说动态实现接口类,在动态生成的实现类里面委托为hanlder去调用原始实现类方法。

比如接口类为Abo,实现类为AboImpl,AboImpl的代理类为$ProxyAoImpl ,那么$ProxyAoImpl 能赋值给Abo?能够赋值给AboImpl?

$ProxyAoImpl 是能够赋值给Abo的,因为前者间接实现了后者,但是$ProxyAoImpl 不能赋值给AboImpl因为他们没有继承或者实现关系。所以回顾下自己项目中Rpc里面autowired时候都是对bo类进行的,而不是对boimpl,并且我们的boimpl类一般都是配置了事务切面被代理过的。

对应Cglib则使用的继承机制,具体说被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,如果被代理类有接口,那么代理类也可以赋值给接口。

另外JDK代理只能对接口进行代理,Cglib则是对实现类进行代理。

动态代理 aop切面实现事务管理的更多相关文章

  1. Spring -- <tx:annotation-driven>注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别。

    借鉴:http://jinnianshilongnian.iteye.com/blog/1508018 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional ...

  2. 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。

    基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...

  3. Spring事务Transactional和动态代理(三)-事务失效的场景

    系列文章索引: Spring事务Transactional和动态代理(一)-JDK代理实现 Spring事务Transactional和动态代理(二)-cglib动态代理 Spring事务Transa ...

  4. 浅析DispatchProxy动态代理AOP

    浅析DispatchProxy动态代理AOP(代码源码) 最近学习了一段时间Java,了解到Java实现动态代理AOP主要分为两种方式JDK.CGLIB,我之前使用NET实现AOP切面编程,会用Fil ...

  5. Spring AOP事务管理(使用切面把事务管理起来)

    在<Spring Transaction 分析事务属性(事务的基本概念.配置)>基础上 http://blog.csdn.net/partner4java/article/details/ ...

  6. Spring ( 四 )Spring的AOP动态代理、切面编程

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.AOP切面编程 1.什么是AOP AOP是面向切面编程.全称:Aspect Oriented Pro ...

  7. spring aop 声明式事务管理

    一.声明式事务管理的概括 声明式事务(declarative transaction management)是Spring提供的对程序事务管理的方式之一. Spring的声明式事务顾名思义就是采用声明 ...

  8. Spring学习8-Spring事务管理(AOP/声明式式事务管理)

    一.基础知识普及 声明式事务的事务属性: 一:传播行为 二:隔离级别 三:只读提示 四:事务超时间隔 五:异常:指定除去RuntimeException其他回滚异常.  传播行为: 所谓事务的传播行为 ...

  9. spring mvc + mybatis + spring aop声明式事务管理没有作用

    在最近的一个项目中,采用springMVC.mybatis,发现一个很恼人的问题:事务管理不起作用!!网上查阅了大量的资料,尝试了各种解决办法,亦未能解决问题! spring版本:3.0.5 myba ...

随机推荐

  1. LibreOJ #113. 最大异或和

    二次联通门 : LibreOJ #113. 最大异或和 /* LibreOJ #113. 最大异或和 线性基 插入 与 查询最大值 说一下我在学习线性基时遇到的一些问题 1.线性基指的是一个数集 2. ...

  2. cdh版hbase构建Phoenix 遇到的坑

    Phoenix 构建cdh版hbase遇到的坑 1. 安装phoenix 下载:在github上下载对应版本https://github.com/apache/phoenix 解压:略 编译: 修改根 ...

  3. MySQL数据分析-(10)SQL基础操作之表操作

    大家好,我是jacky,很高兴跟大家继续分享MySQL数据分析实战课程,前面我们学习了库层面增删改查的SQL语句,这次课jacky将给大家介绍表层面的增删改查, (一)本课时的学习逻辑 表层面的增删改 ...

  4. 浅谈 es6 箭头函数, reduce函数介绍

    今天来谈一下箭头函数, es6的新特性 首先我们来看下箭头函数长什么样子, let result = (param1, param2) => param1+param2; 上述代码 按照以前书写 ...

  5. Jenkins修改显示语言为中文

    1 安装插件 主界面 -> 系统管理 -> 插件管理 -> 可选插件 1.1 安装插件Locale plugin 1.2 安装插件Localization: Chinese(Simp ...

  6. Qt configure 参数

    在编译QT前,可加各种参数来定制自己想要的QT库.这对需要裁减QT库的朋友来说非常重要.对于如何编译QT,可以参考:http://hi.baidu.com/agassi%5Fp/blog/item/4 ...

  7. Python 自学笔记(一)

    1.打印函数 1-1.print()函数 1-1-1.引号的用法 一.单引号与双引号:直接输出 二.三引号:保留原来的格式 1-2.转义字符 转义字符是一种特殊的字符常量,在编程语言中,我们用转义字符 ...

  8. 如何配置WAMP环境(主要是Apache与PHP)

    1.配置Apache 1.编辑Apache配置文件---http.conf(位于安装目录下的conf子目录内): 2.修改Document Root 和 Directory选项,这是修改Apache的 ...

  9. oracle传输表空间

    https://blog.csdn.net/ch7543658/article/details/39271135/ Oracle expdp/impdp常用性能优化方法 1.查看操作系统endiann ...

  10. kotlin 类的继承

    与Java不同,kotlin 使用冒号,而Java 中使用extends, 注意冒号后面需要调用夫类的构造器.属于单继承,使用open 关键字允许继承class package loaderman.d ...