предисловие
Только лысая голова может стать сильнее.
Текст был включен в мой репозиторий GitHub, добро пожаловать, звезда:GitHub.com/Zhongf UC очень…
Я считаю, что все часто используют управление транзакциями Spring, но оно может быть ограничено только одним@Transactional
примечание или вXML
Настройте материалы, связанные с транзакциями, в . Во всяком случае, каждый деньвозможныйДостаточно для нас, чтобы использовать. Но как программист, будь то для интервью или лучшего контроля над кодом, который вы пишете, вы должны больше узнать о деталях транзакций Spring.
Здесь я задаю несколько вопросов, чтобы посмотреть, сможете ли вы ответить на них мгновенно:
- есливложенные вызовыМетод, содержащий транзакцию, к какой точке знаний он относится в управлении транзакциями Spring?
- Фреймворк, который мы используем, может быть
Hibernate/JPA
илиMybatis
известно, что нижний слой нуждается вsession/connection
объекты, помогающие нам выполнять операции. Чтобы обеспечить целостность транзакций, нам нужно использовать несколько наборов операций с базой данных.тот самыйsession/connection
Object, и мы знаем, что объекты, управляемые Spring IOC, по умолчаниюсинглтонДа, почему мы не вызовем проблем с безопасностью потоков при его использовании? Что именно Spring делает внутри? - Что люди называют БПП?
- Каковы важные интерфейсы управления весенней транзакцией?
Во-первых, прочитайте основы, необходимые для этой статьи
Мои одноклассники, прочитавшие эту статьюдефолтУ каждого есть определенное понимание знаний, связанных с транзакциями Spring. (ps: если вы не понимаете конкретную статью, прочитайте ее и вернитесь сюда)
Мы все знаем, что транзакция Spring — одна из лучших практик Spring AOP, так что скажемБазовые знания входа в АОП (простая настройка, использование)нужно знать в первую очередь. Если вы хотите узнать больше об АОП, вы можете прочитать эту статью:Важные точки знаний АОП (введение в терминологию, всестороннее использование). Когда дело доходит до АОП, мы должны сказатьОсновополагающий принцип АОП: динамический шаблон проектирования прокси.. На данный момент у нас уже есть базовое понимание АОП. Так что мы можемИспользуйте XML/аннотацию для настройки управления транзакциями Spring.
В исследовании МОК можно узнать следующее:Жизненный цикл Beans in Spring (извлечение объектов BPP)иОбъекты, управляемые IOC, по умолчанию являются одноэлементными: шаблон проектирования одноэлементного, если одноэлементный объект имеет "государство"(с переменными-членами) несколько потоков, обращающихся к этому одноэлементному объекту, могут привести к небезопасности потока. ТогдаЧто такое потокобезопасность?, есть много способов решить потокобезопасность, но один из них:Пусть у каждого потока будет своя переменная: ThreadLocal
Если вы не очень хорошо разбираетесь в пунктах знаний, о которых я упоминал выше, рекомендуется щелкнуть синее слово, чтобы узнать его.
2. Два примера ненадежной интуиции
2.1 Первый пример
Друг задал мне пример раньше:
Бросить исключение на уровне сервиса и поймать его на уровне контроллера.Если в сервисе есть исключение, будет ли отменена транзакция?
// Service方法
@Transactional
public Employee addEmployee() throws Exception {
Employee employee = new Employee("3y", 23);
employeeRepository.save(employee);
// 假设这里出了Exception
int i = 1 / 0;
return employee;
}
// Controller调用
@RequestMapping("/add")
public Employee addEmployee() {
Employee employee = null;
try {
employee = employeeService.addEmployee();
} catch (Exception e) {
e.printStackTrace();
}
return employee;
}
япервая реакция: Не откатится.
- Тогда я подумал: потому что сервисный уровень выдал исключение, перехваченное контроллером. Откат или нет должен определяться логикой в блоке кода перехвата контроллера.Если блок кода перехвата не откатывается, его не следует откатывать.
Но мой друг сказал после тестирования, что его можно откатить. (папапа бьет по лицу)
Глядя на документацию, в исходной документации говорится:
By default checked exceptions do not result in the transactional interceptor marking the transaction for rollback and instances of RuntimeException and its subclasses do
Вывод: если это исключение времени компиляции, оно не будет автоматически откатываться,Если это исключение во время выполнения, оно автоматически откатится!
2.2 Второй пример
Второй пример взят из статьи Zhihu @ willow, соответствующий URL-адрес будет указан в конце статьи.
Мы все знаем, что с@Transactional
Метод, заключенный в аннотации, может управляться транзакциями Spring, тогда, если яИспользуйте нетранзакционный метод для вызова транзакционного метода в текущем классе, что будет с нашим звонком на этот раз? Будет ли бизнес?
Опишите это в коде:
// 没有事务的方法去调用有事务的方法
public Employee addEmployee2Controller() throws Exception {
return this.addEmployee();
}
@Transactional
public Employee addEmployee() throws Exception {
employeeRepository.deleteAll();
Employee employee = new Employee("3y", 23);
// 模拟异常
int i = 1 / 0;
return employee;
}
Мой первый инстинкт: это связано с механизмом распространения транзакций Spring.
На самом деле это связано с механизмом распространения транзакций Spring.это не имеет значения, позвольте мне сказать вам:
- Управление транзакциями Spring использует АОП, а нижний уровень АОП использует динамический прокси. Итак, если мы пометим аннотацию в классе или методе
@Transactional
, затемпрокси-объект.
Далее позвольте мне проиллюстрировать это картинкой:
Очевидно, что мы получаем прокси (Proxy) объект, вызовaddEmployee2Controller()
метод, в то время какaddEmployee2Controller()
Логика метода такова.target.addEmployee()
, который вызывает исходный объект (цель)addEmployee()
.所以这次的调用Бизнеса нет вообще, не говоря уже о механизме распространения транзакций Spring.
Исходные данные:
Результат теста: транзакции нет вообще
2.2.1 Расширьте его еще немного
Из приведенного выше теста мы можем обнаружить, что если в этом классе нет метода транзакции для вызова аннотации аннотации@Transactional
метода, окончательный вывод заключается в том, что транзакции нет. Затем, если я аннотирую метод этой аннотациейперейти кСуществуют ли какие-либо транзакции с другими объектами службы?
@Service
public class TestService {
@Autowired
private EmployeeRepository employeeRepository;
@Transactional
public Employee addEmployee() throws Exception {
employeeRepository.deleteAll();
Employee employee = new Employee("3y", 23);
// 模拟异常
int i = 1 / 0;
return employee;
}
}
@Service
public class EmployeeService {
@Autowired
private TestService testService;
// 没有事务的方法去调用别的类有事务的方法
public Employee addEmployee2Controller() throws Exception {
return testService.addEmployee();
}
}
Результаты теста:
Поскольку мы используем прокси-объект (Proxy) для вызоваaddEmployee()
метод, то, конечно, есть бизнес.
Прочитав эти два примера, как вы думаете,3-летняя интуиция - настоящая вода!
3. Механизм распространения транзакций Spring
есливложенные вызовыМетод, содержащий транзакцию, к какой точке знаний он относится в управлении транзакциями Spring?
в текущемСодержит методы транзакций, которые вызывают другие методы внутри(независимо от того, содержит метод транзакцию или нет), это относится к категории точек знаний механизма распространения транзакций Spring.
Транзакции Spring основаны на Spring AOP, динамическом прокси-сервере, используемом в нижней части Spring AOP.Существует два способа динамического прокси:
- Прокси на основе интерфейса (прокси JDK)
- На основе прокси интерфейса любой метод классазакрытая модификация,илиИспользуется статическое ключевое словоукрашение, эти методы не могут быть улучшены с помощью Spring AOP
- На основе прокси-сервера CGLib (прокси подкласса)
- На основе прокси подкласса любой метод классаИспользовать приватную, статическую, окончательную модификацию, то ни один из этих методов нельзя улучшить с помощью Spring AOP.
Что касается того, почему описанную выше ситуацию нельзя улучшить, просто подумайте об этом своими мозгами, и вы поймете.
Стоит отметить: те методы, которые нельзя улучшить с помощью Spring AOPНе можетРаботал в деловой среде. пока ониВызывается методом внешней транзакции, из-за уровня распространения управления транзакциями Spring внутренние методы также могутРаботаинициируется внешним методомв контексте транзакции.
Что касается нескольких уровней механизма распространения транзакций Spring, я не буду их здесь публиковать. Это просто для того, чтобы еще раз объяснить, «какова область действия механизма распространения транзакций Spring».
В-четвертых, проблема многопоточности
Фреймворк, который мы используем, может быть
Hibernate/JPA
илиMybatis
известно, что нижний слой нуждается вsession/connection
объекты, помогающие нам выполнять операции. Чтобы гарантировать целостность транзакции, нам нужноНесколько групп операций с базой данных должны использовать один и тот жеsession/connection
Object, и мы знаем, что объекты, управляемые Spring IOC, по умолчаниюсинглтонДа, почему мы не вызовем проблем с безопасностью потоков при его использовании? Что именно Spring делает внутри?
Вспомните, как мы писали Mybaits, когда училисьКласс инструмента сеанса?
Да, используется ThreadLocal, и Spring тоже использует ThreadLocal.
Следующий контент взят из «Освоение Spring 4.x»
Мы знаем, что, как правило, только Bean без сохранения состояния может использоваться совместно только в многопоточной среде, в Spring подавляющее большинство Bean может быть объявлено как одноэлементная область. Spring обусловлен тем, что некоторые компоненты Bean (такие как RequestContextHolder,TransactionSynchronizationManager, LocaleContextHolder и т. д.) «объекты состояния», которые не являются потокобезопасными, инкапсулируются ThreadLocal, что делает их также потокобезопасными «объектами состояния».
Мы можем попробовать щелкнуть TransactionSynchronizationManager, чтобы посмотреть:
5. Что такое ППП?
Полное название BBP называется: BeanPostProcessor, обычно мы называем егопостпроцессор объекта
- Проще говоря, через BeanPostProcessor мы можем "Обработка".
Управляемые bean-компоненты Spring (или жизненный цикл Bean) также являютсяобычный тестОчки знаний, я также набираю осеньюсноваЯ разобрал шаги, потому что это важнее, поэтому выложу здесь:
- ResouceLoader загружает информацию о конфигурации
- BeanDefintionReader анализирует информацию о конфигурации и генерирует BeanDefintion один за другим.
- BeanDefintion управляется BeanDefintionRegistry
- BeanFactoryPostProcessor обрабатывает информацию о конфигурации (то есть обрабатывает информацию о конфигурации, обычно реализуемую через PropertyPlaceholderConfigurer)
- создавать экземпляры бобов
- если фасоль
配置/实现
Если InstantiationAwareBean установлен, вызовите соответствующий метод - Используйте BeanWarpper для завершения настройки атрибутов (зависимости) между объектами.
- если фасоль
配置/实现了
Осведомленный интерфейс, затем вызовите соответствующий метод - Если Bean сконфигурирован с помощью метода before BeanPostProcessor, он вызывается
- Если bean-компонент сконфигурирован с
init-method
Или реализуйте InstantiationBean, затем вызовите соответствующий метод - Если Bean настроен с помощью метода after BeanPostProcessor, он вызывается
- Поместить объекты в HashMap
- Наконец, если настроен метод destroy или DisposableBean, выполняется операция уничтожения.
Также есть фотографии про БПП:
5.1 Почему вы конкретно говорите о BPP?
Нижний уровень программирования Spring AOP — технология динамического прокси, которую необходимо использовать при вызовепрокси-объект. Так как же это делает Spring?
Мне нужно только написать BPP, в методе PostProcessfoediNiTialization или постпроцессафициализации или постпроцессафициализации, судите объект, чтобы увидеть, нужно ли оно вплетено в аспектную логику, при необходимости, я буду генерировать прокси-объект на основе этого объекта, а затем вернуть Прокси-объект, то окончательная инъекция в контейнер, естественно, является прокси-объектом.
Spring предоставляет BeanPostProcessor, который позволяет нам "Обработка"Какие!
6. Поймите несколько важных интерфейсов транзакций Spring
Транзакции Spring можно разделить на два типа:
- Программные транзакции (реализация транзакций с помощью кода)
- Декларативные транзакции (транзакции реализуются конфигурацией)
Программные транзакции относительно просто реализовать в Spring, а декларативные транзакции реализовать гораздо сложнее, потому что они инкапсулируют множество вещей (обычно мы используем простые, а они очень сложные).
В программных транзакциях есть несколько важных интерфейсов:
- TransactionDefinition: определяет Spring-совместимыйСвойства транзакции(например, уровень изоляции транзакций, распространение транзакций, тайм-аут транзакции, статус только для чтения)
- TransactionStatus: представляет специфику транзакции.Рабочий статус(Чтобы получить информацию о текущем статусе транзакции, вы также можете использовать этот интерфейскосвенныйоткат транзакций и др.)
- PlatformTransactionManager: интерфейс диспетчера транзакций (определяет набор поведений, а конкретная реализация выполняется с помощью различных платформ сохраняемости ---аналогияJDBC)
В декларативных транзакциях помимо интерфейсов TransactionStatus и PlatformTransactionManager есть несколько важных интерфейсов:
- TransactionProxyFactoryBean: создание прокси-объектов
- TransactionInterceptor: Реализовать перехват объекта
- TransactionAttrubute: данные конфигурации транзакции.
Наконец
В этой статье в основном рассказывается о некоторых наиболее важных знаниях об управлении транзакциями Spring.Конечно, в процессе обучения есть и другие знания.Если вы хотите продолжить обучение, вы можете продолжить чтение справочных материалов, приведенных ниже. .
Использованная литература:
- В те годы мы вместе гонялись за Весной
- «Знание практики разработки корпоративных приложений Spring 4.x»
- "Инсайдер технологии Spring"
рад вывестигалантерейные товарыОбщедоступный номер технологии Java: Java3y. В паблике более 200 статейоригинальныйТехнические статьи, обширные видеоресурсы, красивые карты мозга — идите сюдаобрати внимание нанемного!
Я думаю, что моя статья хорошо написана, пожалуйста, нажмитеотличный!