• 自己实现一个简单的数据库事务


    原理:通过Spring提供的BeanPostProcessor来对使用了事务注解的类进行动态代理,通过spring提供的获取数据库连接工具类DataSourceUtils来获取连接。

    只有两个类 MyTransactional 和 TransactionBeanPostProcessor,MyTransactional 为自定义的事务方法注解,TransactionBeanPostProcessor生成动态代理。

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface MyTransactional {
    
    }
    @Component
    public class TransactionBeanPostProcessor implements BeanPostProcessor{
        
        
        private static final Logger logger = LoggerFactory.getLogger(TransactionBeanPostProcessor.class);
        
        @Autowired
        private DataSource datasource;
        
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (!getNeedTransactionMethods(bean).isEmpty()) {
                //jdk原生动态代理只支持实现接口的类做代理.
                bean = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), 
                        bean.getClass().getInterfaces(), new TransactionInvocationHandler(bean));
                logger.info("generate transaction proxy for "+bean.getClass());
            }
            return bean;
        }
        
        private static List<Method> getNeedTransactionMethods(Object bean) {
            Method[] methods = bean.getClass().getMethods();
            List<Method> transactionMethods = new ArrayList<>();
            for(Method method : methods) {
                if (method.isAnnotationPresent(MyTransactional.class)) {
                    transactionMethods.add(method);
                }
            }
            return transactionMethods;
        }
        
        
        /**
         * 使用动态代理来植入数据库事务逻辑
         * Created by 01385234 on 2019年10月23日.
         */
        public class TransactionInvocationHandler implements InvocationHandler{
            
            private Object proxyObject;
            
            
            public TransactionInvocationHandler(Object proxyObject) {
                super();
                this.proxyObject = proxyObject;
            }
    
    
    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Method objMethod = proxyObject.getClass().getMethod(method.getName(), method.getParameterTypes());
                if (objMethod.isAnnotationPresent(MyTransactional.class)) {
                    TransactionSynchronizationManager.initSynchronization();
                    //统一用spring提供的工具类DataSourceUtils来获取数据库连接,该connection放入threadlocal中,
                    //mybatis中使用的connection也从该threadlocal中取,从而保证了同一个事务中使用同一个connection。
                    Connection connection = DataSourceUtils.doGetConnection(datasource);
                    connection.setAutoCommit(false);
                    try {
                        method.invoke(proxyObject, args);
                        connection.commit();
                    }catch(Exception e) {
                        logger.error("事务方法:{},args:{}出现异常,方法回滚",method,args);
                        connection.rollback();
                        throw e;
                    }
                }
                
                return method.invoke(proxyObject, args);
            }
            
        }
    }
  • 相关阅读:
    学习方法和阶段介绍 、 iOS界面开发引入 、 构造第一个App 、 视图控制器和视图 、 控件与事件 、 InterfaceBuilder
    Runtime 、 Block
    NSDictionary 、 NSMutableDictionary
    NSArray(二) 、 NSMutableArray 、 NSSet 、 NSMutableSet
    NSNumber 、 NSValue 、 日期处理 、 集合类 、 NSArray(一)
    (Foundation)NSObject 、 NSString 、 NSMutableString
    Objective-c---分类 、 扩展 、 ARC
    Objective-C--- 多态 、 协议
    关于Quartz2D方法小总结
    控制器之间的顺传与逆传
  • 原文地址:https://www.cnblogs.com/swave/p/11732680.html
Copyright © 2020-2023  润新知