What is a transaction? Do you understand how transactions work? Can you implement Spring transaction principles yourself? Let’s test ourselves to see if we know anything. So let’s look at spring-related transactions
concept
Transactions have ACID properties.
A series of operations that are performed as a single logical unit of work, either completely or not.
The underlying Spring transactions rely on MySQL transactions, which are implemented using AOP at the code level. MySQL has the concept of an isolation level for transactions, only InnoDB has transactions and is implemented using undo log and redo log.
With AOP, there are join points, pointcuts, enhancements, targets, and weaves. Refer to the Introduction to Spring AOP, which uses TransactionInceptor to intercept transactions at the code level and then process them.
System parsing Spring transaction principles article:
- Introduction to Spring AOP
- Spring AOP enhancements (Advice)
- Spring Bean lifecycle
- Spring AOP implementation principles
- Spring Transaction Principles
code
- In AopConfigUtils, you can see exactly what type of AutoProxyCreator is generated, which are beanPostProcessors that customize the instance of the Bean after it is created. If you use the @ EnableTransactionManagement, after some configuration is generated InfrastructureAdvisorAutoProxyCreator this time, Specific how to generate this class point in @ EnableTransactionManagement inside.
EnableTransactionManagement
-> @Import(TransactionManagementConfigurationSelector.class)
-> returnnew String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; - > AutoProxyRegistrar. - > create InfrastructureAdvisorAutoProxyCreator registerBeanDefinitionsCopy the code
-
In the Bean’s life cycle, the Bean has been created called create InfrastructureAdvisorAutoProxyCreator. PostProcessAfterInitialization method.
Another AbstractAutowireCapableBeanFactory initializeBean method also worth a look
Get Advice for the Bean and, if any, create a dynamic proxy for the Bean. If you want to create a CGLib proxy, you need to create a CGLib proxy (proxyTargetClass=true). If you want to create a CGLib proxy, you need to create a CGLib proxy (proxyTargetClass=true). The main use of Enhancer classes
Cglib (1)–Enhancer
Intercept (Object proxy, Method Method, Object[] args, MethodProxy MethodProxy) has the data that we want to intercept according to the conditions, and it can be judged according to the parameters.
-
You can talk with in DefaultAdvisorChainFactory. See getInterceptorsAndDynamicInterceptionAdvice method
PointcutAdvisor for BeanFactoryTransactionAttributeSourceAdvisor MethodMatcher for TransactionAttributeSourcePointcutCopy the code
The resulting interceptor is a transaction interceptor, and since it is a transaction interceptor, you can follow the previous analysis.
Spring transaction principle analysis
- Let’s see why the interceptor we got is MethodInterceptor. There are AdvisorAdapter in methodMatcher.match
And Advice of advisor, advisor is BeanFactoryTransactionAttributeSourceAdvisor
- A default in TransactionProxyFactoryBean TransactionIntercetor
- In the default @ EnableTransactionManagement annotations, set the BeanFactoryTransactionAttributeSourceAdvisor advice to TransactionIntercetor, This step of annotation is in effect, as we discussed in the first step.
- Method is how to match, TransactionAttributeSourcePointcut matches in the method, called TransactionAttributeSource judgment whether there is a method of attribute
Then call computeTransactionAttribute (method, targetClass), if there is a transaction attribute judgment
AbstractFallbackTransactionAttributeSource.computeTransactionAttribute --> AnnotationTransactionAttributeSource. DetermineTransactionAttribute method attributes - > get TransactionAttribute, and then returnCopy the code
- So far we’ve basically explained how Spring’s transaction interceptors work, when the interceptors are set, and how the transaction methods match.
Transaction invalid
- Private methods will not take effect. The JDK must be an interface. Interfaces cannot have private methods. The reason is that Spring internally determines that method modifiers that are not public do not generate transaction interception proxy classes.
- When CGLib agents are present, final methods do not take effect and nullPointExceptions are thrown, CGLib and JDK internals.
Finally, why does calling a transactionmethod from a non-transactionmethod on the current bean not work?
public int save(String name, int age) throws Exception {
insert(name, age);
return 1;
}
@Transactional
public void insert(String name, int age){
jdbcTemplate.update("insert into user(id,name,age)values(1,'"+name+"',"+age+")");
jdbcTemplate.update("insert into user(id,name,age)values(2,'"+name+"',"+age+")");
jdbcTemplate.update("insert into user(id,name,age)values(1,'"+name+"',"+age+")");
}
Copy the code
A:
After final verification, the following conclusions are drawn:
If the save method is called first, when method interception is performed, the method interceptor first gets the original object proxied by the currently dynamically proxied object.
For example, when FirstApp generates a dynamic proxy named FirstApp$CGlibxxx, the getTarget object is the instance of FirstApp.
Next, if the current method, such as the save method, is determined to have no Advice(enhanced), then the original object method is called directly. In this case, the firstApp.save method is called. Instead of the FirstApp$CGLibxxx save method. Can follow the code.
The last
Spring transactions, if you carefully read my article, I believe you will gain a lot
reference
- Introduction to Spring AOP
- Spring AOP enhancements (Advice)
- Spring Bean lifecycle
- Spring AOP implementation principles
- Spring Transaction Principles