第三方框架整合,依然使用MyBatis作为整合对象,之前我们已经使用xml方式整合了MyBatis,现在使用注解方式无非就是将xml标签替换为注解,将xml配置文件替换为配置类而已,原有xml方式整合配置如下:
使用@Bean将DataSource和SqlSessionFactoryBean存储到Spring容器中,而MapperScannerConfigurer使用注解@MapperScan进行指明需要扫描的Mapper在哪个包下,使用注解整合MyBatis配置方式如下:
@Configuration
@ComponentScan("com.itheima")
@MapperScan("com.itheima.mapper")
public class ApplicationContextConfig {@Beanpublic DataSource dataSource(@Value("${jdbc.driver}") String driver,@Value("${jdbc.url}") String url,@Value("${jdbc.username}") String username,@Value("${jdbc.password}") String password){DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName(driver);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}@Beanpublic SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource);return sqlSessionFactoryBean;}
}
注解方式,Spring整合MyBatis的原理,关键在于@MapperScan,@MapperScan不是Spring提供的注解,而是MyBatis为了整合Spring,在整合包org.mybatis.spring.annotation中提供的注解,源码如下:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({MapperScannerRegistrar.class})
@Repeatable(MapperScans.class)
public @interface MapperScan {String[] value() default {};String[] basePackages() default {};Class>[] basePackageClasses() default {};Class extends Annotation> annotationClass() default Annotation.class;// ... ...
}
重点关注一下@Import({MapperScannerRegistrar.class}),当@MapperScan被扫描加载时,会解析@Import注解,从而加载指定的类,此处就是加载了MapperScannerRegistrar
MapperScannerRegistrar实现了ImportBeanDefinitionRegistrar接口,Spring会自动调用registerBeanDefinitions方法,该方法中又注册MapperScannerConfigurer类,而MapperScannerConfigurer类作用是扫描Mapper,向容器中注册Mapper对应的MapperFactoryBean,前面讲过,此处不在赘述了:章节地址
public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {// 默认执行registerBeanDefinitions方法void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes annoAttrs, BeanDefinitionRegistry registry, String beanName) {BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);// ... 省略其他代码 ...// 注册BeanDefinitionregistry.registerBeanDefinition(beanName, builder.getBeanDefinition());}
}
Spring与MyBatis注解方式整合有个重要的技术点就是@Import,第三方框架与Spring整合xml方式很多是凭借自定义标签完成的,而第三方框架与Spring整合注解方式很多是靠@Import注解完成的。
@Import可以导入如下三种类:
⚫ 普通的配置类
⚫ 实现ImportSelector接口的类
⚫ 实现ImportBeanDefinitionRegistrar接口的类
@Import导入实现了ImportSelector接口的类
@Configuration
@ComponentScan("com.itheima")
@Import({MyImportSelector.class})public class ApplicationContextConfig {
}
public class MyImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {// 返回要进行注册的Bean的全限定名数组return new String[]{User2.class.getName()};}
}
ImportSelector接口selectImports方法的参数AnnotationMetadata代表注解的媒体数据,可以获得当前注解修饰的类的元信息,例如:获得组件扫描的包名
public class MyImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {// 获得指定类型注解的全部信息Map annotationAttributes = annotationMetadata.getAnnotationAttributes(ComponentScan.class.getName());// 获得全部信息中basePackages信息String[] basePackages = (String[]) annotationAttributes.get("basePackages");// 打印结果是com.itheimaSystem.out.println(basePackages[0]);return new String[]{User2.class.getName()};}
}
@Import导入实现ImportBeanDefinitionRegistrar接口的类,实现了该接口的类的registerBeanDefinitions方法会被自动调用,在该方法内可以注册BeanDefinition
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 使用给定的BeanDefinitionRegistry参数,手动注册BeanDefinitionBeanDefinition beanDefinition = new RootBeanDefinition();beanDefinition.setBeanClassName("com.itheima.pojo.User2");registry.registerBeanDefinition("user2", beanDefinition);}
}
上一篇:【网络安全】记一次APP登录爆破
下一篇:【audio】TM8211