анализ исходного кода mybatis
Анализ процесса mybatis
Прежде всего, исходный код mybatis делится на два случая:
- только мибатис
- Исходный код Mybatis, интегрированный с Spring
Анализ исходного кода в этих двух случаях будет немного отличаться, например, если анализируется режим mybatis+spring, то запуск mybatis начинается с инициализации spring.
С чего начинается mybatis с интеграцией spring
Прежде всего, когда я анализирую интеграцию mybatis и spring, в основном возникают две ассоциации.
- @MapperScan
- @Bean---->SqlSessionFactoryBean
Зная из исходного кода, что MapperScan на самом деле в основном использует технологию импорта Spring и точку расширения Spring ImportBeanDefinitionRegistrar, А @Bean просто использует технологию javaconfig для настройки объекта. Если вы разбираетесь в технологии Spring, вы можете знать, что первый импорт, обработанный Spring, — это MapperScan.
@MapperScan
Если вы знакомы с Spring и разбираетесь в процессе инициализации Spring, то знаете, что инициализацию Spring можно условно разделить на две части.
- Работа перед созданием экземпляра SpringBean
- работать в экземпляре spring и после него
Работа до создания экземпляра SpringBean
Анализируя исходный код, можно сделать вывод, что @MapperScan в основном делает 3 вещи.
- Отсканируйте BeanDefinition, соответствующий всем преобразователям.
- Превратите маппер в FactoryBean, BeanDefinition of MapperFactoryBean
- Добавьте значение конструктора в BeanDefinition, поскольку mybatis MapperFactoryBean имеет конструктор параметров,
Когда Spring создает экземпляр этого объекта, ему требуется значение конструктора, которое является классом, и spring позже в процессе создания экземпляра. Верните наш прокси-объект в соответствии с этим классом
# 1.把mapper变成FactoryBean
MapperScannerRegistrar.registerBeanDefinitions()
ClassPathMapperScanner.doScan()
ClassPathMapperScanner.processBeanDefinitions()
//这里就是将这个class传递到有参构造方法
definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); // issue #59
//将所有的mapper接口改为MapperFactoryBean类
definition.setBeanClass(this.mapperFactoryBean.getClass());
public MapperFactoryBean(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public T getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}
# 2.spring实例化该BeanDefinition
ConstructorResolver.autowireConstructor()
//将传递给构造器的参数,获取到传递过来的mappeer接口
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
Работа во время и после весеннего создания экземпляра
Mybatis в основном использует точку расширения исходного метода Spring для завершения инициализации информации об отображении, такой как инициализация операторов sql, здесь Основной точкой расширения Spring является afterPropertiesSet.Если вы хорошо разбираетесь в Spring, вы будете знать механизм afterPropertiesSet Как это работает?Проще говоря, это использование MapperFactoryBean для реализации initialzingBean, потому что MapperFactoryBean — это FactoryBean, мы понимаем его как маппер, поэтому мы можем понять, что он получает свою собственную информацию, а затем кэширует информацию, кэшируется на карте. mappedStatements
org.apache.ibatis.session.Configuration#mappedStatements
org.springframework.dao.support.DaoSupport#afterPropertiesSet
org.mybatis.spring.mapper.MapperFactoryBean#checkDaoConfig
org.apache.ibatis.session.configuration#addMapper(this.mapperInterface);
org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#parse();
org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#parseStatement()
关键代码
SqlSource sqlSource = getSqlSourceFromAnnotations(method, parameterTypeClass, languageDriver);
Связанная блок-схема
Различные проблемы с кешем первого уровня mybatis
1. Почему mybatis не работает при интеграции кэша первого уровня spring?
Поскольку пакет интеграции mybatis и spring расширяет класс sqlSessionTemplate, этот класс внедряется в Mapper при запуске контейнера Spring. Этот класс заменяет исходный DefaultSqlSession. Все методы запросов в SqlSessionTemplate не являются прямыми запросами, а проходят через прокси-объект. Прокси-объект расширяет методы запроса, в основном закрывая сеанс.
- Анализ основного принципа:
- Отслеживая исходный код, вы можете видеть, что этот sqlSession был изменен на sqlSessionTemplate.
*
- Войдя в класс sqlSessionTemplate, вы обнаружите, что исходный DefaultSqlSession был улучшен.
- Затем перейдите к следующему шагу, вы увидите invocationHandler (динамический прокси-сервер jdk), который достиг прокси-класса DefaultSqlSession.
По сравнению с собственным запросом сопоставления mybatis, вы можете видеть, что собственный запрос использует объект DefaultSqlSession для запроса.
Резюме: анализируя исходный код, вы можете увидеть принцип инвалидации кэша первого уровня mybatis, который является усовершенствованием sqlSessionTemplate. Мысль: зачем вам закрывать sqlSession здесь?
Поскольку mybatis и spring интегрированы, сопоставитель, управляемый mybatis, напрямую передается управлению spring, но mybatis не предоставляет sqlSession для spring, поэтому, когда spring завершает выполнение кода, он больше не может получить объект sqlSession, поэтому здесь только spring После завершения выполнения sqlSession можно закрыть, что никак.
Как инициализируется mybatis после интеграции spring и mybatis?
1. Как mybatis сканирует интерфейс картографа?
Как обсуждалось выше, после интеграции mybatis и spring все интерфейсы картографов mybatis передаются для обработки в MapperFactoryBean. MapperFactoryBean — это объект FactoryBean, а фактически возвращаемый объект — это объект, возвращаемый методом getObject().
- Войдите в этап анализа исходного кода:
- 1. Просканируйте все интерфейсы картографов mybatis через @MapperScan. Принцип заключается в использовании точки расширения весеннего импорта (ImportBeanDefinitionRegistrar).
- 2. Реализовать ImportBeanDefinitionRegistrar, переписать метод registerBeanDefinitions, получить объект реестра и зарегистрировать компоненты в контейнере Spring.
- 3. Запустите сканирование интерфейса маппера
- 4. Обработать полученный при сканировании интерфейс маппера. Например: добавить свойства, установить режим автосвязывания, изменить beanClass, добавить параметры конструктора и т. д.
Резюме: Здесь в основном работа по инициализации интерфейса маппера, и самое главное, он имеет три функции. 1. С помощью аннотации @MapperScan примените технологию импорта для выполнения сканирования картографа. 2. Измените маппер, полученный сканированием, измените beanClass и используйте FactoryBean для унифицированной обработки. 3. Измените режим автоматического связывания beanDefinition на автоматическое связывание свойств объекта MapperFactoryBean без использования @Autowired, чтобы избежать обязательных зависимостей от spring.
2. Как создается интерфейс Mapper mybatis?
-
1. Назначение свойства объекта MapperFactoryBean интерфейса картографа.
Глядя на MapperFactoryBean, вы можете увидеть соответствующие свойства.В настоящее время предполагается, что следующие свойства должны быть автоматически подключены: 1.mapperИнтерфейс 2. добавить в конфигурацию 3.setSqlSessionFactory() 4.setSqlSessionTemplate()
- Следующее анализируется путем отслеживания исходного кода:
- Затем проследите до метода autowireByType.
Резюме: MapperFactoryBean нужны автоматически подключаемые свойства: sqlSessionFactory, addToConfig.
-
2. После создания экземпляра интерфейса MapperFactoryBean, как сканировать sql.xml или аннотации, соответствующие интерфейсу картографа?
Реализован интерфейс InitializingBean, переопределен метод afterPropertiesSet(), а затем инициализирован в этом методе. Вопрос: Почему бы не использовать @PostConstruct, а реализовать интерфейс InitializingBean?
Из-за реализации интерфейса InitializingBean метод afterPropertiesSet() был переписан. Таким образом, инициализация mybatis заключается в ожидании инициализации всех свойств, прежде чем инициализировать содержимое mybatis, например сканирование картографа и другие операции.
Посмотрите структуру MapperFactoryBean: MapperFactoryBean ---> SqlSessionDaoSupport ---> DaoSupport ---> импл InitializingBean Все могут получить MapperFactoryBean, который реализует интерфейс InitializingBean.
InitializingBean — это технология Spring, которая реализует этот класс и требует переопределения метода afterPropertiesSet(). afterPropertiesSet(), как следует из названия, выполняется после автоматической сборки всех свойств класса.
- Отследить анализ исходного кода:
Сводка по интеграции Spring и mybatis
На данный момент здесь представлены все ключевые моменты интеграции mybatis в Spring. Резюмируя ключевые моменты: 1. @MapperSacn, импорт, ImportBeanDefinitionRegistrar 2.FactoryBean, InitializingBean, AutowireMode