1. Введение
В процессе разработки системных приложений обычно необходимо использовать транзакции для обеспечения согласованности бизнес-данных.Методы реализации: открытие транзакций, выполнение операций записи в базу данных, фиксация или откат транзакций.Этот стандартный метод реализации подходит для небольшое количество согласованных сервисов.Если существует большое количество предприятий, которым необходимо обеспечить согласованность данных, это не только заставит разработчиков повторять кодирование, но и приведет к избыточному коду в системе. На основе этих вопросов отличноSpring
Фреймворк предоставляет нам@Transactional
Аннотации, так как же они используют аннотации для решения наших проблем? Как нам его проанализировать?
SpringBoot
Интегрированные функции часто исходят изxxxAutoConfiguration
начать говорить
2. Автоматическая настройка
ОткрытымTransactionAutoConfiguration
Классы автоматической настройки могут видеть более важную аннотацию@EnableTransactionManagement
Используется для включения функции управления транзакциями,@EnableTransactionManagement
Аннотации снова импортируютсяAutoProxyRegistrar
иProxyTransactionManagementConfiguration
2.1 Конфигурация транзакции
ProxyTransactionManagementConfiguration
объявляет аспект вBeanFactoryTransactionAttributeSourceAdvisor
, убедитесь, что в касательной плоскости должны быть соответствующие точки касанияTransactionAttributeSourcePointcut
(для объявления врезок) и уведомленийTransactionInterceptor
(Последующие действия для достижения поставленной цели).
2.2 Заявление@Transactional
Процессор аннотаций
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
AnnotationTransactionAttributeSource
инстанцирование указывает, что анализатор аннотацийSpringTransactionAnnotationParser
Вы можете видеть, что парсер в основном используется для обработки@Transactional
аннотация
2.3 Внедрение автоматического регистратора прокси
существует2.自动配置
упомянул@EnableTransactionManagement
также представилAutoProxyRegistrar
,В направленииIOC
Влить в контейнерInfrastructureAdvisorAutoProxyCreator
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
InfrastructureAdvisorAutoProxyCreator
ДостигнутоBeanPostProcessor
интерфейс, с перехватом и дескрипторомBean
Способность
2.3.1 Bean
Постобработка
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
2.3.2 Получить все из контейнераAdvisor
/**
* Find all candidate Advisors to use in auto-proxying.
* @return the List of candidate Advisors
*/
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
2.3.3 Отфильтровать подходящиеAdvisor
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
// 1.获取切点对应的MethodMatcher
MethodMatcher methodMatcher = pc.getMethodMatcher();
for (Class<?> clazz : classes) {
// 2.获取当前类中的所有方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
// 3.判断是否符合切点要求,此处的methodMatcher为TransactionAttributeSourcePointcut
if (methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
Судя по тому, есть ли@Transactional
Аннотация, если есть, используйтеSpringTransactionAnnotationParser
разобрать и сгенерироватьTransactionAttribute
2.3.4 Advisor
Сортировать
sortAdvisors(eligibleAdvisors);
2.3.4 Резюме
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 1.从容器中获取所有类型为Advisor的切面
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 2.筛选出符合条件的切面(也就是类或方法上被@Transactional注解标注)
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 3.对符合条件的切面进行升序排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
2.4 Выбор метода прокси
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!IN_NATIVE_IMAGE &&
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
Class<?> targetClass = config.getTargetClass();
// 1.如果实现接口则选择jdk代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 2.选择cglib代理
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
2.4.1 Создание прокси
здесь сcglib
Например
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
try {
Class<?> rootClass = this.advised.getTargetClass();
Class<?> proxySuperClass = rootClass;
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
Callback[] callbacks = getCallbacks(rootClass);
}
}
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Choose an "aop" interceptor (used for AOP calls).
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
}
СоздайтеEnhancer
и укажите обратный вызов какDynamicAdvisedInterceptor
2.5 Вызов прокси
Выполнение целевого метода проксируемого объектаuserService.saveUser(user);
будет вызван, когдаDynamicAdvisedInterceptor
изintercept()
метод
2.5.1 Отфильтруйте те, которые соответствуют условиямAdvice
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// 1.遍历所有满足条件的Advisor,也就是2.3.3章节返回的Advisor
for (Advisor advisor : advisors) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
// 2. 判断是否满足切点要求
boolean match = mm.matches(method, actualClass);
// 3.满足切点要求
if (match) {
// 3. 获取切面对应的通知,也就是TransactionInterceptor
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// 4.返回满足条件的通知
return interceptorList;
}
2.5.2 Выполнение условногоAdvice
@Override
@Nullable
public Object proceed() throws Throwable {
// 1.如果没有advice可以执行,则执行目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 2.从advice列表中取出一个advice
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 3.执行advice的invoke方法,也就是TransactionInterceptor的invoke
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
3. Вызов транзакции
3.1 Получить свойства конфигурации транзакции
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
это@Transactional
Свойства, объявленные в аннотациях
3.2 Получить диспетчер транзакций
final TransactionManager tm = determineTransactionManager(txAttr);
получить из контейнераDataSourceTransactionManagerAutoConfiguration
Менеджер транзакций, объявленный в классе автоконфигурацииJdbcTransactionManager
public class DataSourceTransactionManagerAutoConfiguration {
@Bean
@ConditionalOnMissingBean(TransactionManager.class)
JdbcTransactionManager transactionManager(DataSource dataSource,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
JdbcTransactionManager transactionManager = new JdbcTransactionManager(dataSource);
transactionManagerCustomizers.ifAvailable((customizers) -> customizers.customize(transactionManager));
return transactionManager;
}
}
3.3 Выполнение транзакций
4. Резюме
@Transactional
Три элемента принципа реализации切面
,切点
,通知
-
InfrastructureAdvisorAutoProxyCreator
Постпроцессор перехватывает всеBean
- Итерация по всем типам
Advisor
из切面
- вернуться довольным
切点
условный切面
список - Выберите метод прокси
- Создать прокси
- перечислить
通知
изinvoke()
метод- открытая транзакция
- позвонить другим
通知
изinvoke()
метод, если целевой метод не выполняется - Выполнить исключение, откатить транзакцию
- Выполнить успешно, зафиксировать транзакцию
- Выполнить целевой метод
учиться@Transactional
Принцип реализации аннотаций позволяет не только切面
,切点
,通知
Четкое понимание также позволяет нам выполнять аналогичные функции с помощью его идей, таких как@Cache
Аннотации реализуют кэширование приложений,@Async
Аннотация реализует асинхронное выполнение бизнеса