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 objectObject 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;}@Overridepublic 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;}@Overridepublic 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则是对实现类进行代理。

转载于:https://www.cnblogs.com/mxz1994/p/7249255.html

动态代理 aop切面实现事务管理相关推荐

  1. 浅入浅出代理模式与Spring事务管理

    本文回顾了代理模式和Spring事务管理的原理. 前言 最近在开发业务代码的时候,犯了一个事务注解的错误:在同一个类的非事务方法中调用了另一个事务方法,导致事务没有生效,如下所示: public Co ...

  2. Spring 整合 Mybatis - 二(切面、事务管理)

    紧接着上篇<Spring 整合 Mybatis - 一(基础)>,介绍Spring 整合 Mybatis的切面.事务管理. 1 增加切面aop功能 1.1 spring.xml sprin ...

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

    在<Spring Transaction 分析事务属性(事务的基本概念.配置)>基础上 1.使用基于注解的AOP事务管理  <tx:annotation-driven transac ...

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

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

  5. AOP||动态代理||AOP专业术语;

    AOP:(Aspect Oriented Programming)面向切面编程: OOP:(Object Oriented Programming )面向对象编程: 面向切面编程:基于OOP基础之上新 ...

  6. Spring-Boot的动态代理AOP原理

    前言 Spring AOP使用了动态代理技术,动态代理在业界比较流行的实现方式有,CGLIB,Javassist,ASM等等. Spring动态代理实现方式 Spring采用了JDK和CGLIB两种方 ...

  7. spring中使用动态代理(AOP)

    spring是整合了BGLIB和JDK两种动态代理 示例:使用CGLIB代理 public class MyCar {private String color = "blue";p ...

  8. Java--JDK动态代理(AOP)

    一.代理模式 百度百科的定义 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. ...

  9. spring aop 声明式事务管理

    http://www.cnblogs.com/wangkaipeng/p/5782116.html

  10. 使用动态代理简单模拟一下spring的事务管理

    按照平时写代码的习惯,我们会定义一个service接口 package com.proxy.test; public interface UserService {public void sayHel ...

最新文章

  1. Laravel使用之七牛对象存储
  2. 第一次scrapy爬虫记录
  3. [css] css中的baseline,你知道吗?
  4. pop3常用命令记录
  5. 话费直充/三网直冲/联通直充/电信直充/移动直充/系统源码
  6. 华为5G微交易修复版源码 K线/结算全修复 去短信+去邀请码
  7. php的ob函数详解
  8. properties加载的几种方式
  9. java.util.concurrent.atomic.AtomicBoolean 源码
  10. 基于RV1126平台imx291分析 --- rkcif_mipi注册
  11. 计算机网络自顶向下-第 8 版
  12. Windows下的conda换源和pip换源
  13. 家用风扇控制系统c语言程序设计,[信息与通信]家用风扇控制系统.doc
  14. win7修改计算机名访问被拒绝访问,今天解答win7无法更改注册表拒绝访问的解决介绍...
  15. 仿微信视频通话大小视图切换(SurfaceView实现)
  16. 文档服务器备份策略,服务器备份策略
  17. 用vuejs仿网易云音乐(实现听歌以及搜索功能)
  18. Python:警告 的11种情况
  19. MySQL中如何设置外键
  20. SG3525matlab,基于SG3525芯片的大功率恒压/恒流LED电源研制 - 全文

热门文章

  1. [HTML5和Flash视频播放器]Video.js 学习笔记(一 ) HLS库:videojs-contrib-hls
  2. [android] 切换界面的通用处理
  3. 10.Configure One-to-Many(配置一对多关系)【Code-First系列】
  4. [Java] ActionEvent 事件处理
  5. 智能安全实验室-杀马(Defendio) 2.5.0.430 :自定义上报威胁
  6. 按值传递时 php必须复制值,PHP开发笔试题及答案(一)
  7. c语言实现sbrk函数,菜鸟随笔(2)---brk()与sbrk()函数的学习与使用
  8. 使用PowerDesigner
  9. 线程同步与互斥:POSIX无名信号量
  10. range 小程序picker_小程序开发讲义【入门篇】 03