1. Предпосылки
Последняя компания разделяет базу данных в соответствии с линейкой продуктов, чтобы выполнять больше действий Mysql, что приводит к множеству источников данных в проекте.Наша линейка продуктов демонтирована первой, поэтому конфигурация этих источников данных и диспетчера транзакций по умолчанию , и используются они нормально. , но после добавления новых источников данных и менеджеров транзакций в другие линейки продуктов транзакция оказалась недействительной, и возникло подозрение, что это связано с методом настройки.
2. Анализ причин
Сначала не говорите много о коде, о том, почему вы кодируете, знаете ли,com
На обратной стороне обычно находится название компании.
на фото выше1Это последнее, последнее на первом месте,
pxhTransactionManager
это не проблема, потому что красивое имяtransactionManager
Он у нас уже занят (первый релиз хорош разве что для исследования ямы), проблема должна лежать и определять его заново<tx:annotation-driven>
Этикетка.
Тут очень странно, вообще все в проекте напрямую
<tx:annotation-driven/>
Просто объявите эту аннотацию, зачем вы хотите ее написать?transaction-manager
Атрибуты, тут мы предполагаем (на самом деле это так), что это дефолтный менеджер указанной транзакции.Так как он дефолтный, то есть дефолтное имя.Да как все думают, дефолтное имяtransactionManager
,фактическиIDEA
Это уже дало нам подсказку, как показано ниже
Бесполезное объявление свойств по умолчанию, и мышка на нем
Alt+Enter
Первую подсказку можно удалить
определить несколько раз
tx
Теги — это странные вещи, которые можно делать в одноэлементном мире.Spring
, и мы можем предположить, основываясь на результатах и коде,<tx:annotation-driven>
Этикетка берет на себя先入为主
Стратегия, которая приводит к тому, что диспетчер транзакций, который мы вызываем по умолчанию, становитсяpxhTransactionManager
, однако это не тот источник данных, который должен вызывать наш код, поэтому откат недопустим.
3. Анализ кода
Угадывание должно основываться на коде, так как теги определены в
XML
файл, то мы начинаем сSpring
Разбор нашего файла конфигурации начинает выглядеть так, как будто мы начинаем сSpring
существуетWeb.xml
Окно запуска, определенное в файле, запускается, как всем известноContextLoaderListener
Listener
обаServletContextListener
Класс реализации запускается при запуске контейнера.contextInitialized
метод, введитеcontextLoader.initWebApplicationContext
метод
Этот метод в основном является контейнер инициализации контекста, бетон
bean
Загрузка и другие методы находятся вconfigureAndRefreshWebApplicationContext()
метод
Войти
wac.refresh()
метод, здесьwac
да классXmlWebApplicationContext
, я не буду говорить о вышесказанном, это слишком раздражает и я не понимаю...
XmlWebApplicationContext
Наследование этого класса очень сложно, вотrefresh()
Фактический код находится вAbstractApplicationContext
в классе
Сразу к теме
obtainFreshBeanFactory()
метод
loadBeanDefinitions(beanFactory)
Разбор методаXML
файл, введитеAbstractXmlApplicationContext
в классеloadBeanDefinitions()
метод
Войти
XmlWebApplicationContext.loadBeanDefinitions()
метод
Войти
AbstractBeanDefinitionReader.loadBeanDefinitions()
ряд перегруженных методов, а затем введитеAbstractBeanDefinitionReader
КатегорияloadBeanDefinitions(String location, Set<Resource> actualResources)
метод
Войти
XmlBeanDefinitionReader
КатегорияloadBeanDefinitions(EncodedResource encodedResource)
метод
проходить через
XmlBeanDefinitionReader
КатегорияdoLoadBeanDefinitions()
способ входаregisterBeanDefinitions()
метод,
Войти
DefaultBeanDefinitionDocumentReader
КатегорияregisterBeanDefinitions(Document doc, XmlReaderContext readerContext)
метод
затем введите
parseBeanDefinitions()
метод
картинаtx:Такие теги относятся к пользовательскому тегу go
BeanDefinitionParserDelegate.parseCustomElement()
метод
Смысл в том, чтобы через пространство имен найти соответствующий класс обработки, ввести
DefaultNamespaceHandlerResolver
Категорияresolve()
метод
ниже
handlerMappings
Соответствие между пространствами имен и классами обработки
Войти
TxNamespaceHandler
class видно, что несколько ключевых классов инициализированы
Вернитесь ко входу прямо сейчас, войдите
NamespaceHandlerSupport.parse()
метод
Видно, что необходимо реализовать
AnnotationDrivenBeanDefinitionParser.parse()
метод
Можно обнаружить, что появились уже знакомые нам пакеты, здесь мы догадываемся, что это тоже своего рода фабричный паттерн, а по сути — это классы обработки различных тегов, которые необходимо ввести в пространство имен. Что нам нужно, чтобы войти, это
spring-tx
пакет, вAnnotationDrivenBeanDefinitionParser
внутренний статический классAopAutoProxyConfigurer
статический методconfigureAutoProxyCreator
является ключом, здесь также объясняется, почему предубеждения,
только если нет такого типа
bean
будет правильно, когдаbean
инициализируется и регистрируется в контейнере, иxml
Синтаксический анализ осуществляется сверху вниз, поэтому менеджер транзакций, который мы разместили ниже, не работает должным образом, а безжалостно отбрасывается.
Также в этой части кода объясняется
transaction-manager
Процесс разбора атрибута тега, здесь также задается значение по умолчанию
существует
TransactionInterceptor
Категорияinvoke()
Метод является конкретным исполнителем прокси-объекта транзакции, а конкретный код находится вTransactionAspectSupport.invokeWithinTransaction()
Добрый,
на фото выше
completeTransactionAfterThrowing
метод, который определяет, что нужно откатить при возникновении исключения, если@Transactional
Аннотация не указанаrollbackFor
свойства, введитеDefaultTransactionAttribute
, так только вRuntimeException
введите исключение иError
откат
4. Решения
На самом деле решения есть онлайн, т.е.@Transactional
Соответствующий менеджер транзакций указывается в аннотации, например@Transactional("pxhTransactionManager")
@Transactional("transactionManager")
См. код ниже для конкретной причины.
TransactionAspectSupport
в классе