[Huangdao principal conta pública tráfego principal projeto de negócios lado de monetização] Assuntos de primavera explicação detalhada @Transactional

Já iniciamos este projeto para 1.0 e a resposta geral é muito boa. Aqueles que são um pouco problemáticos podem ganhar 30-50 por dia, e aqueles que se saem melhor podem ganhar 50-100 + por dia.
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui

Insira a descrição da imagem aqui
Insira a descrição da imagem aqui

Este projeto é muito simples. O que fazemos é a receita de publicidade dos proprietários de tráfego. Uma única leitura de 1.000 ou mais pode gerar mais de dez a vinte receitas, o que é muito maior do que a receita de publicidade de outras plataformas de auto-mídia. Pode-se dizer que é uma renda totalmente passiva, bastando gastar meia hora todos os dias para postar artigos!
Olá a todos, a todos, hoje vou explicar-lhes os princípios dos assuntos da estrutura da primavera.
Existem dois métodos para a transação spring: arquivo de configuração e anotação. O princípio do método do arquivo de configuração não será introduzido aqui. Desta vez, vamos nos concentrar em explicar o princípio da anotação @Transactional.

Um: Processo de princípio de implementação de anotação @Transactional:
Insira a descrição da imagem aqui
1. A varredura de anotação é realizada quando o servidor é iniciado, e todos os métodos com @Transactional são gerados em um objeto proxy aop;
2. Quando o chamador chama o método, ele é cortado no aop, o real O objeto proxy de aop é chamado;
3. A transação jdbc é aberta no objeto proxy aop e o método real é chamado;
4. O objeto proxy aop é confirmado ou retrocedido quando o método é executado.

2: Por que a reversão da transação falha depois que uma exceção é lançada?
Em alguns casos, ocorreu uma exceção e ela foi lançada, mas a reversão falhou. O que está acontecendo? Para entender esse problema, precisamos interpretar o código-fonte da transação do spring em profundidade. O código-fonte do núcleo principal está em org.springframework. .transaction.interceptor.TransactionAspectSupport, o método invokeWithinTransaction controla a lógica da transação, o código-fonte é o seguinte:

protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
    
    
        final TransactionAttribute txAttr = this.getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
        final PlatformTransactionManager tm = this.determineTransactionManager(txAttr);
        final String joinpointIdentification = this.methodIdentification(method, targetClass, txAttr);
        Object result;
        if (txAttr != null && tm instanceof CallbackPreferringPlatformTransactionManager) {
    
    
            final TransactionAspectSupport.ThrowableHolder throwableHolder = new TransactionAspectSupport.ThrowableHolder();

            try {
    
    
                result = ((CallbackPreferringPlatformTransactionManager)tm).execute(txAttr, new TransactionCallback<Object>() {
    
    
                    public Object doInTransaction(TransactionStatus status) {
    
    
                        TransactionAspectSupport.TransactionInfo txInfo = TransactionAspectSupport.this.prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);

                        Object var4;
                        try {
    
    
                            Object var3 = invocation.proceedWithInvocation();
                            return var3;
                        } catch (Throwable var8) {
    
    
                            if (txAttr.rollbackOn(var8)) {
    
    
                                if (var8 instanceof RuntimeException) {
    
    
                                    throw (RuntimeException)var8;
                                }

                                throw new TransactionAspectSupport.ThrowableHolderException(var8);
                            }

                            throwableHolder.throwable = var8;
                            var4 = null;
                        } finally {
    
    
                            TransactionAspectSupport.this.cleanupTransactionInfo(txInfo);
                        }

                        return var4;
                    }
                });
                if (throwableHolder.throwable != null) {
    
    
                    throw throwableHolder.throwable;
                } else {
    
    
                    return result;
                }
            } catch (TransactionAspectSupport.ThrowableHolderException var18) {
    
    
                throw var18.getCause();
            } catch (TransactionSystemException var19) {
    
    
                if (throwableHolder.throwable != null) {
    
    
                    this.logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                    var19.initApplicationException(throwableHolder.throwable);
                }

                throw var19;
            } catch (Throwable var20) {
    
    
                if (throwableHolder.throwable != null) {
    
    
                    this.logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                }

                throw var20;
            }
        } else {
    
    
            TransactionAspectSupport.TransactionInfo txInfo = this.createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

            try {
    
    
                //1.执行调用链,循环调用执行前置方法,真实方法
                result = invocation.proceedWithInvocation();
            } catch (Throwable var16) {
    
    
                //1.2出现异常后,进行处理,回滚事务
                this.completeTransactionAfterThrowing(txInfo, var16);
                throw var16;
            } finally {
    
    
                this.cleanupTransactionInfo(txInfo);
            }
            //2.方法执行顺利,调用后置方法,提交事务
            this.commitTransactionAfterReturning(txInfo);
            return result;
        }
    }

Comentei sobre as linhas de código mais críticas. A lógica geral é executar alguns aspectos do front-end do método real primeiro e, em seguida, executar o método real. Se houver uma exceção, ele será processado (reversão da transação) e se não houver exceção, será submetida a Transação, e implementados métodos de pós-aprimoramento.
Portanto, para entender o motivo da falha na reversão da transação, você precisa explorar mais o método this.completeTransactionAfterThrowing (txInfo, var16). O código-fonte é o seguinte:

protected void completeTransactionAfterThrowing(TransactionAspectSupport.TransactionInfo txInfo, Throwable ex) {
    
    
        if (txInfo != null && txInfo.hasTransaction()) {
    
    
            if (this.logger.isTraceEnabled()) {
    
    
                this.logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "] after exception: " + ex);
            }

            if (txInfo.transactionAttribute.rollbackOn(ex)) {
    
    
                try {
    
    
                    txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
                } catch (TransactionSystemException var7) {
    
    
                    this.logger.error("Application exception overridden by rollback exception", ex);
                    var7.initApplicationException(ex);
                    throw var7;
                } catch (RuntimeException var8) {
    
    
                    this.logger.error("Application exception overridden by rollback exception", ex);
                    throw var8;
                } catch (Error var9) {
    
    
                    this.logger.error("Application exception overridden by rollback error", ex);
                    throw var9;
                }
            } else {
    
    
                try {
    
    
                    txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
                } catch (TransactionSystemException var4) {
    
    
                    this.logger.error("Application exception overridden by commit exception", ex);
                    var4.initApplicationException(ex);
                    throw var4;
                } catch (RuntimeException var5) {
    
    
                    this.logger.error("Application exception overridden by commit exception", ex);
                    throw var5;
                } catch (Error var6) {
    
    
                    this.logger.error("Application exception overridden by commit error", ex);
                    throw var6;
                }
            }
        }

    }

Pode-se ver no código-fonte que o que é processado é o runtime RuntimeException e outras exceções.É por esse motivo que o Spring não tratou algumas exceções fora do tempo de execução quando foram lançadas, então não houve rollback.
O diagrama de relacionamento de integração anormal é o seguinte:
Insira a descrição da imagem aqui
Na figura acima, pode-se ver que, como IO, as exceções SQL não serão revertidas se não passarem por um processamento específico.

No código-fonte, também notamos uma linha de código detalhado txInfo.getTransactionStatus (), que se baseia no status da transação quando a transação é executada. É por isso que o código para reverter manualmente a transação é escrito assim:

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

Clique no código-fonte e você pode ver que o status da transação é falso por padrão (significando confirmado), após chamar este método, ele será alterado para verdadeiro (rollback)

public abstract class AbstractTransactionStatus implements TransactionStatus {
    
    
    private boolean rollbackOnly = false;
    private boolean completed = false;
    private Object savepoint;

    public AbstractTransactionStatus() {
    
    
    }

    public void setRollbackOnly() {
    
    
        this.rollbackOnly = true;
    }
    ………………

Portanto, em resumo, há dois motivos para a reversão da transação de primavera:
1. A exceção lançada é uma exceção de não tempo de execução RuntimeException;
2. O status da transação é modificado artificialmente.

Então, há uma maneira de resolver esse problema?
Claro, se for artificial, você só precisa encontrar o código correspondente para ajustar ou excluir;
se for uma exceção não operacional, o Spring também fez uma solução para este problema. Existem duas opções
1. Configure rollbackFor:
@ Transactional (rollbackFor = Exception.class)
2. Reverter manualmente a transação.
Depois de capturar a exceção, chame o código de posição: TransactionAspectSupport.currentTransactionStatus (). SetRollbackOnly (); Por fim, lance a exceção.

rollbackFor diz ao framework spring para capturar exceções fora do tempo de execução e revertê-las. = Exception.class informa o escopo do framework spring a ser capturado. Portanto, também podemos personalizar exceções e apenas obter exceções específicas para rollback.

Acho que você gosta

Origin blog.csdn.net/ncw8080/article/details/113857831
Recomendado
Clasificación