当前位置: 首页 > news >正文

重庆千牛建设工程有限公司网站wordpress中英文网站

重庆千牛建设工程有限公司网站,wordpress中英文网站,模板之家html5,十大经典事件营销案例分析我们在定义Repository的时候通常定义的时一个接口#xff0c;而并没有去实现这个接口#xff0c;那么Jpa是如何让开发者无需自己实现接口就可以使用Repository去操作数据库#xff1f; 动态代理#xff01;#xff01;#xff01; Repository原理 试想一下JPA是如何做的… 我们在定义Repository的时候通常定义的时一个接口而并没有去实现这个接口那么Jpa是如何让开发者无需自己实现接口就可以使用Repository去操作数据库 动态代理 Repository原理 试想一下JPA是如何做的 通过动态代理将接口实例化成对应的类。解析方法名或根据指定的方法名并根据得到的结果转换为数据库操作 尝试写一个示例 自定义一个Repository public interface CustomRepositoryT, ID extends RepositoryT, ID {/*** 查询前num条数据* param num* return*/ListT findByFirst(Long num); }对自定义Repository的代理逻辑 /*** author yuanmengfan(mf.yuan qq.com) on 2024/8/7 23:26* 自定义Repository的代理*/ Data public class CustomRepositoryInvocationHandler implements InvocationHandler {// 用于操作数据库private EntityManager em;// 知晓操作那个对象private Class? entityClass;public CustomRepositoryInvocationHandler(EntityManager em, Class? entityClass) {this.em em;this.entityClass entityClass;}Overridepublic Object invoke(Object proxy, Method method, Object[] args) {Object result null;String name method.getName();switch (name) {// 根据方法名定义不同操作数据库的逻辑case findByFirst:CriteriaBuilder cn em.getCriteriaBuilder();CriteriaQuery query cn.createQuery(entityClass);Root from query.from(entityClass);result em.createQuery(query.select(from)).setMaxResults(Math.toIntExact((Long) args[0])).getResultList();break;}return result;} }测试下创建出来的代理对象是否能正常运行 Testpublic void test() {// 初始化IOC容器AnnotationConfigApplicationContext applicationContext new AnnotationConfigApplicationContext(JpaConfig.class);LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean applicationContext.getBean(LocalContainerEntityManagerFactoryBean.class);// 创建EntityManagerEntityManager em localContainerEntityManagerFactoryBean.getNativeEntityManagerFactory().createEntityManager();Class? proxyClass UserCustomRepository.class;// 获取接口泛型信息ParameterizedType parameterizedType (ParameterizedType) proxyClass.getGenericInterfaces()[0];Type[] actualTypeArguments parameterizedType.getActualTypeArguments();Class entityClass (Class) actualTypeArguments[0];Class idClass (Class) actualTypeArguments[1];// 通过动态代理创建对象UserCustomRepository proxyInstance (UserCustomRepository) Proxy.newProxyInstance(proxyClass.getClassLoader(), new Class[]{proxyClass}, new CustomRepositoryInvocationHandler(em, entityClass));System.out.println(proxyInstance.findByFirst(5L));}已经可以根据我们指定的类型来操作数据库了。 源码跟踪验证 Test public void test(){// 初始化IOC容器AnnotationConfigApplicationContext applicationContext new AnnotationConfigApplicationContext(JpaConfig.class);UserJpaRepository bean applicationContext.getBean(UserJpaRepository.class);OptionalTUser byId bean.findById(5L); }能发现这里在IOC容器中的是代理对象。 可以明显的看出这里是使用的JDK动态代理。 这里可以看见实际上我们的对象是SimpleJpaRepository 实际调用findById也是通过EntityManage去操作数据库 Spring是如何整合Jpa呢 疑问 怎么知道要注册那些Repository ComponentScanComponent // 添加 ComponentScan(basePackages com.mfyuan) public class JpaConfig{}// 添加 Component public interface UserCustomRepository extends CustomRepositoryTUser, Long {}Test public void test1() {// 初始化IOC容器AnnotationConfigApplicationContext applicationContext new AnnotationConfigApplicationContext(JpaConfig.class);// 尝试从容器中获取BeanUserCustomRepository bean applicationContext.getBean(UserCustomRepository.class); }为什么还是拿不到这个Bean呢 因为Repository是接口不是类不会被注册到IOC容器中。在扫描成BeanDefinition是被过滤掉了。 ConfigurationClassParser#doProcessConfigurationClass ComponentScanAnnotationParser#parse 处理Component的解析 ClassPathBeanDefinitionScanner#doScan #findCandidateComponents #scanCandidateComponents #isCandidateComponent(metadataReader) 判断是否包含Component注解 #isCandidateComponent(sbd) 判断是否为接口或者抽象类 ::: 如何解决不扫描接口的问题呢 ClassPathBeanDefinitionScanner自定义一个扫描器让接口也可以别扫描到。BeanDefinitionRegistryPostProcessor在BeanDefinition注册的过程中可以允许进干预。 ::: public class CustomClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {public CustomClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {super(registry);// 添加过滤器只扫描实现CustomRepository接口的类}/*** 允许接口被扫描** param beanDefinition the bean definition to check* return*/Overrideprotected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {AnnotationMetadata metadata beanDefinition.getMetadata();return metadata.isInterface();} }Component public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {CustomClassPathBeanDefinitionScanner definitionScanner new CustomClassPathBeanDefinitionScanner(registry);// 清空原有filter definitionScanner.resetFilters(false);// 添加过滤器只扫描实现CustomRepository接口的类definitionScanner.addIncludeFilter(new AssignableTypeFilter(CustomRepository.class));// 能将 com.mfyuan.repository 下的接口也进行注册了definitionScanner.scan(com.mfyuan.repository);}Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {BeanDefinitionRegistryPostProcessor.super.postProcessBeanFactory(beanFactory);} }到现在我们的接口就可以被扫描成BeanDefinition但是又遇到一个问题 与之前的错误不同的是已经不再提前找不到对应类型的Bean了而是接口不能实例化的。 ::: 如何将对应的Repository接口注入到容器中 可以将通过动态代理后的对象放入到容器中这里就解决了接口不能实例化的问题。 但是不可能一个一个去创建动态代理的对象吧这样想想就很痛苦。 使用FactoryBean来定义创建过程。与前面Repository原理结合。 ::: Data public class CustomRepositoryFactoryBean implements FactoryBean {private Class? repositoryInterface;Autowiredprivate LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean;public CustomRepositoryFactoryBean(Class? repositoryInterface) {this.repositoryInterface repositoryInterface;}/*** FactoryBean的特性这个方法的返回值是注册到容器中对象*/Overridepublic Object getObject() {// 创建EntityManagerEntityManager em localContainerEntityManagerFactoryBean.getNativeEntityManagerFactory().createEntityManager();// 获取接口泛型信息ParameterizedType parameterizedType (ParameterizedType) repositoryInterface.getGenericInterfaces()[0];Type[] actualTypeArguments parameterizedType.getActualTypeArguments();Class? entityClass (Class?) actualTypeArguments[0];// Class idClass (Class) actualTypeArguments[1];// 通过动态代理创建对象return Proxy.newProxyInstance(repositoryInterface.getClassLoader(), new Class[]{repositoryInterface}, new CustomRepositoryInvocationHandler(em, entityClass));}/*** FactoryBean的特性这个方法的返回值是注册到容器的对象类型*/Overridepublic Class? getObjectType() {return repositoryInterface;} }重写CustomClassPathBeanDefinitionScanner#doScan 对扫描到的BeanDefinition进行修改 public class CustomClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {// .....SneakyThrowsOverrideprotected SetBeanDefinitionHolder doScan(String... basePackages) {// 这里拿到的就行自定义扫描器 扫出来的所有BeanDefinitionSetBeanDefinitionHolder beanDefinitionHolders super.doScan(basePackages);for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {ScannedGenericBeanDefinition beanDefinition (ScannedGenericBeanDefinition) beanDefinitionHolder.getBeanDefinition();// 得到扫描到的repositoryClassString repositoryClassName beanDefinition.getBeanClassName();// 设置BeanDefinition的Class为FactoryBean// mybatis 这里也是这样做的 只不过是新注册了一个BeanDefinitionbeanDefinition.setBeanClass(CustomRepositoryFactoryBean.class);// 添加一个构造参数beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(repositoryClassName);}return beanDefinitionHolders;} }测试 Test public void test1() {// 初始化IOC容器AnnotationConfigApplicationContext applicationContext new AnnotationConfigApplicationContext(JpaConfig.class);// 尝试从容器中获取BeanUserCustomRepository bean applicationContext.getBean(UserCustomRepository.class);System.out.println(bean.findByFirst(5L)); }能够走自定义Repository里面的方法了。 解释 CustomRepository相当于一个顶层接口他去定义对应的统一的数据库操作。类似JpaRepositoryCrudRepository等 CustomRepositoryInvocationHandler相当于是对顶层接口所有的方法进行了一个实现。类似SimpleJpaRepository 源码验证 // 导入JpaRepositoriesRegistrar Import(JpaRepositoriesRegistrar.class) public interface EnableJpaRepositories {}// 实现了ImportBeanDefinitionRegistrar就代表有动态注册BeanDefinition的能力 class JpaRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport {}public abstract class RepositoryBeanDefinitionRegistrarSupportimplements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {Overridepublic void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry,BeanNameGenerator generator) {// ...// 委托RepositoryConfigurationDelegate进行注册RepositoryConfigurationDelegate delegate new RepositoryConfigurationDelegate(configurationSource, resourceLoader,environment);delegate.registerRepositoriesIn(registry, extension);}Overridepublic StreamableBeanDefinition getCandidates(ResourceLoader loader) {// 定义的扫描器RepositoryComponentProvider scanner new RepositoryComponentProvider(getIncludeFilters(), registry);scanner.setConsiderNestedRepositoryInterfaces(shouldConsiderNestedRepositories());scanner.setEnvironment(environment);scanner.setResourceLoader(loader);getExcludeFilters().forEach(scanner::addExcludeFilter);// 查找满足条件的组件return Streamable.of(() - getBasePackages().stream()//.flatMap(it - scanner.findCandidateComponents(it).stream()));} }public class RepositoryConfigurationDelegate {// ...public ListBeanComponentDefinition registerRepositoriesIn(BeanDefinitionRegistry registry,RepositoryConfigurationExtension extension) {CollectionRepositoryConfigurationRepositoryConfigurationSource configurations extension.getRepositoryConfigurations(configurationSource, resourceLoader, inMultiStoreMode);} }public abstract class RepositoryConfigurationExtensionSupport implements RepositoryConfigurationExtension {public T extends RepositoryConfigurationSource CollectionRepositoryConfigurationT getRepositoryConfigurations(T configSource, ResourceLoader loader, boolean strictMatchesOnly) {// ...// 调用RepositoryBeanDefinitionRegistrarSupport.getCandidates 获得合适的对象for (BeanDefinition candidate : configSource.getCandidates(loader)) {}// ...} }class RepositoryComponentProvider extends ClassPathScanningCandidateComponentProvider {public RepositoryComponentProvider(Iterable? extends TypeFilter includeFilters, BeanDefinitionRegistry registry) {// ....if (includeFilters.iterator().hasNext()) {for (TypeFilter filter : includeFilters) {addIncludeFilter(filter);}} else {// 添加 是Repository接口的类super.addIncludeFilter(new InterfaceTypeFilter(Repository.class));// 添加定义了RepositoryDefinition注解的类super.addIncludeFilter(new AnnotationTypeFilter(RepositoryDefinition.class, true, true));}// 排除带有NoRepositoryBean注解的类addExcludeFilter(new AnnotationTypeFilter(NoRepositoryBean.class));}Overridepublic SetBeanDefinition findCandidateComponents(String basePackage) {// 这里就走到的Spring的findCandidateComponents 里面// 关键的两个方法则是isCandidateComponent(metadataReader) 与 isCandidateComponent(sbd)SetBeanDefinition candidates super.findCandidateComponents(basePackage);// ...}// 这样的话就能将Repository接口及RepositoryDefinition扫描成BeanDefinition了protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {for (TypeFilter tf : this.excludeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return false;}}for (TypeFilter tf : this.includeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return isConditionMatch(metadataReader);}}return false;}Overrideprotected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {boolean isNonRepositoryInterface !ClassUtils.isGenericRepositoryInterface(beanDefinition.getBeanClassName());boolean isTopLevelType !beanDefinition.getMetadata().hasEnclosingClass();boolean isConsiderNestedRepositories isConsiderNestedRepositoryInterfaces();return isNonRepositoryInterface (isTopLevelType || isConsiderNestedRepositories);} }public abstract class RepositoryFactoryBeanSupportT extends RepositoryS, ID, S, IDimplements InitializingBean, RepositoryFactoryInformationS, ID, FactoryBeanT, BeanClassLoaderAware,BeanFactoryAware, ApplicationEventPublisherAware {public void afterPropertiesSet() {// ...// 传入repositoryInterface来得到代理对象this.repository Lazy.of(() - this.factory.getRepository(repositoryInterface, repositoryFragmentsToUse));// ...} }public abstract class RepositoryFactorySupport implements BeanClassLoaderAware, BeanFactoryAware {public T T getRepository(ClassT repositoryInterface, RepositoryFragments fragments) {// ...// 这里就是最终创建代理对象的地方会判断是JDK动态代理还是CGLIB代理T repository (T) result.getProxy(classLoader);// ...return repository;} } EnableJpaRepositories(basePackages com.mfyuan.repository)Import(JpaRepositoriesRegistrar.class)JpaRepositoriesRegistrar实现ImportBeanDefinitionRegistrar拥有动态注册的能力与BeanDefinitionRegistryPostProcessor一样自定义扫描器RepositoryComponentProvide添加扫描Repository口及RepositoryDefinition注解的includeFilter及NoRepositoryBean注解的excludeFilter将扫描成功的获选Bean的信息创建成BeanDefinition并修改它的BeanClassName实际是JpaRepositoryFactoryBeanJpaRepositoryFactoryBean是一个BeanFactory会为我们创建出一个动态代理的对象并放入到IOC容器中。
http://www.w-s-a.com/news/876767/

相关文章:

  • 房天下网站建设女生说wap是什么意思
  • 网站开发安全机制北京做网站多少钱合理
  • 扁平化 公司网站建设大型视频网站需要的资金量
  • 免费建各种网站淄博网站建设yx718
  • 凡科网建站入门教程运城市网站建设
  • 黄浦区未成年人思想道德建设网站oa系统是什么
  • 微信里的网站怎么做电子商务网站开发平台
  • 易企秀网站怎么做轮播图网站建设张世勇
  • 网站备案幕布尺寸建立网页的几个步骤
  • pc网站页面找出网站所有死链接
  • 专业做seo的网站网站内连接
  • 阿里云网站开发服务器想开网站建设公司
  • 网站开发不足之处茶叶seo网站推广与优化方案
  • 响应式网站建设系统网站优化怎么做 有什么技巧
  • 班级网站做哪些方面wordpress标签 扩展
  • 如何在电商上购物网站Wordpress 域名授权插件
  • 网站建设后台怎么弄昆明如何做好关键词推广
  • 自己怎么做个网站优酷视频网站开发
  • 2015做网站前景电子商务营销的发展现状
  • 官方网站建设情况说明电子商务网站开发的形式有
  • 网站建设玖金手指排名11专业建站公司建站系统
  • 全球排名前十网站百度网站官网网址
  • 商家在携程旅游网站怎样做宣传做网站公司苏州
  • 芜湖做网站都有哪些广州音乐制作公司
  • 青岛好的网站制作推广注册公司流程步骤
  • 怎么制作营销网站模板wordpress苗木模板
  • 手机网站样例wordpress 排序
  • 济南网站建设手机网站开发人员需要去做原型吗
  • 动易网站模板下载微信支付 wordpress
  • 学校建设外文网站情况阿里云 建设网站怎么样