Mybatis 接口编程中dao 层接口没有注解和<bean> 为什么能被实例化为bean??

Spring整合MyBatis原理之MapperScannerConfigurer(一) 目录前言`spring` 整合 `mybatis` 原理1. 类 `MapperScannerConfigurer`类 `MapperScannerConfigurer` 小结2. 类 `SqlSessionFactoryBean`类 `SqlSessionFactoryBean` 小结3. 解析 `DAO` 文件解析 `DAO` 文件小结4. `DAO` 接口被调用`spring` 整合 `mybatis` 原理流程步骤 前言 spring 和 mybatis 进行整合时,需要使用以下这个依赖包 < 阅读详情

Mybatis 接口编程中dao 层接口没有注解和 为什么能被实例化为bean??

相信不少人有过这个疑问,我自己带着这个疑问好久了!我自己写dao 层接口都是自己加上@Repository这个注解,但是项目组的其他同事不写的情况也可以正常注入?带着这个疑问我一点一点查找资料。最终发现 MapperScannerConfigurer 帮我们做了实例化bean的工作。

在Spring配置Mybatis的文件中我们可以看到如下代码:
[html] view plain copy 在CODE上查看代码片派生到我的代码片

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
<property name="basePackage" value="org.tarena.note.dao">  
</property>  

MapperScannerConfigurer,让它扫描特定的包,自动帮我们成批地创建映射器。这样就大大减少了配置的工作量。
basePackage属性是让你为映射器接口文件设置基本的包路径。可以使用分号或逗号作为分隔符设置多于一个的包路径。每个映射器都会在指定的包路径中递归地被搜索到。被发现的映射器将会使用spring对自动侦测组件默认的命名策略来命名。也就是说,如果没有发现注解,它就会使用映射器的非大写的非完全限定类名。如果发现了@Component或JSR-330@Named注解,它会获取名称。
通过上面的配置,spring就会帮助我们对test.mybatis.dao下面所有接口进行自动的注入,而不需要为每个接口重复在Spring配置文件中进行声明了。那么这个功能如何做到的呢?MapperScanner Configurer中又有哪些核心操作呢?同样首先看下这个类实现了InitializingBean接口。马上查找afterPropertiesSet方法来看看类的初始化逻辑。
[java] view plain copy 在CODE上查看代码片派生到我的代码片

public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {  

但没有任何有意义的实现,我们看到MapperScannerConfigurer还实现了接口BeanDefinitionRegistryPostProcessor接口的方法:
[java] view plain copy 在CODE上查看代码片派生到我的代码片

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {  
  if (this.processPropertyPlaceHolders) {  
    processPropertyPlaceHolders();  
  }  

  ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);  
  scanner.setAddToConfig(this.addToConfig);  
  scanner.setAnnotationClass(this.annotationClass);  
  scanner.setMarkerInterface(this.markerInterface);  
  scanner.setSqlSessionFactory(this.sqlSessionFactory);  
  scanner.setSqlSessionTemplate(this.sqlSessionTemplate);  
  scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);  
  scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);  
  scanner.setResourceLoader(this.applicationContext);  
  scanner.setBeanNameGenerator(this.nameGenerator);  
  scanner.registerFilters();  
  scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));  
}  

正是这里。大致看下代码实现,正是完成了对指定路径扫描的逻辑。那么,我们就以此为入口,详细地分析MapperScannerConfigurer所提供的逻辑实现
1.processPropertyPlaceHolders属性的处理
首先,难题就是processPropertyPlaceHolders属性的处理。或许许多人并未接触过此属性。我们只能查看processPropertyPlaceHolders()函数来反推此属性所代表的功能。
[java] view plain copy 在CODE上查看代码片派生到我的代码片

private void processPropertyPlaceHolders() {  
  Map<String, PropertyResourceConfigurer> prcs = applicationContext.getBeansOfType(PropertyResourceConfigurer.class);  

  if (!prcs.isEmpty() && applicationContext instanceof GenericApplicationContext) {  
    BeanDefinition mapperScannerBean = ((GenericApplicationContext) applicationContext)  
        .getBeanFactory().getBeanDefinition(beanName);  

    // PropertyResourceConfigurer does not expose any methods to explicitly perform  
    // property placeholder substitution. Instead, create a BeanFactory that just  
    // contains this mapper scanner and post process the factory.  
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();  
    factory.registerBeanDefinition(beanName, mapperScannerBean);  

    for (PropertyResourceConfigurer prc : prcs.values()) {  
      prc.postProcessBeanFactory(factory);  
    }  

    PropertyValues values = mapperScannerBean.getPropertyValues();  

    this.basePackage = updatePropertyValue("basePackage", values);  
    this.sqlSessionFactoryBeanName = updatePropertyValue("sqlSessionFactoryBeanName", values);  
    this.sqlSessionTemplateBeanName = updatePropertyValue("sqlSessionTemplateBeanName", values);  
  }  
}  

此函数的说明给我嗯进行了说明:BeanDefinitionRegistries会在应用启动的时候调用,并且会早于BeanFactoryPostProcessors的调用,这就意味着PropertiesResourceConfigurers还没有被加载所有对于属性文件的引用将会失效,为避免此种情况发生,此方法手动地找出定义的PropertyResourceConfigurers并进行调用以以保证对于属性的引用可以正常工作。
下面我们举个例子说明:
如果在配置文件中添加如下代码 :

<bean class="org.mybatis.Spring.mapper.MapperScannerConfigurer">  
      <property name="basePackage" value="${basePackage}"/>  
</bean>  

此时你会发现这个配置并没有生效。因为在解析MapperScannerConfigurer这个bean的时候,配置文件还没有被加载,为了解决这个问题,Spring提供了processPropertyPlaceHloder属性,你需要这样配置MapperScannerConfigurer类型的bean:

<bean class="org.mybatis.Spring.mapper.MapperScannerConfigurer">  
      <property name="basePackage" value="${basePackage}"/>  
      <property name="processPropertyPlaceHolders" value="true">  
</bean>  

通过processPropertyPlaceHolders属性的配置,将程序引入我们正在分析的processPropertyPlaceHolders函数中来完成属性文件的加载。至此,我们理清了这个函数的属性,再回顾看下这个函数做的事情:
(1)找到所有已经注册的PropertyResourceConfigurer类型的bean。
(2)模拟Spring的环境来用处理器。这里通过使用呢new DefaultlistableBeanFactory()来模拟Spring中的环境(完成处理器的调用后便失效),将映射的bean,也就是MapperScannerConfigurer类型bean注册到环境中来进行后处理器的调用。
2.根据配置属性生成过滤器
在postProcessBeanDefinitionRegistry方法中可以看到,配置中支持很多属性的设定,但是我们感兴趣的或者说影响扫描结果的并不多,属性设置后通过在scanner.registerFilters()代码中生成对应的过滤器来控制扫描结果。

public void registerFilters() {  
  boolean acceptAllInterfaces = true;  

  // if specified, use the given annotation and / or marker interface  
  //对于annotationClass属性的处理  
  /* 
   *如果annotationClass不为空,表示用户设置了此属性,那么就要根据此属性生成过滤器以保证达到用户 
   *想要的效果,而封装此属性的过滤器就是AnnotationTypeFilter.AnnotationTypeFilter保证在扫描对应 
   *java文件时只接受标记有注解为annotationClass接口  
   */  
  if (this.annotationClass != null) {  
    addIncludeFilter(new AnnotationTypeFilter(this.annotationClass));  
    acceptAllInterfaces = false;  
  }  

  // override AssignableTypeFilter to ignore matches on the actual marker interface  
  //对于markerInterface属性的处理  
  if (this.markerInterface != null) {  
    addIncludeFilter(new AssignableTypeFilter(this.markerInterface) {  
      @Override  
      protected boolean matchClassName(String className) {  
        return false;  
      }  
    });  
    acceptAllInterfaces = false;  
  }  

//全局默认处理
/*
* 在上面两个属性中如果存在其中任何属性,acceptAllInterfaces的值将会被改变,但是如果用户没有设定以上的属性
* 那么,Spring会为我们增加一个默认的过滤器实现TypeFilter接口的局部类,旨在接受所有接口文件。
*/

  if (acceptAllInterfaces) {  
    // default include filter that accepts all classes  
    addIncludeFilter(new TypeFilter() {  
      public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {  
        return true;  
      }  
    });  
  }  

  // exclude package-info.java  
  //不扫描package-info.java文件  
  addExcludeFilter(new TypeFilter() {  
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {  
      String className = metadataReader.getClassMetadata().getClassName();  
      return className.endsWith("package-info");  
    }  
  });  
}  

从上面的函数我们可以看出,控制扫描文件Spring通过不同的过滤器完成,这些定义的过滤器记录在了includeFilters和excludeFilters属性中。

public void addIncludeFilter(TypeFilter includeFilter){  
       this.includeFilters.add(includeFilter);  
}  

public void addExcludeFilter(TypeFilter excludeFilter){  
       this.excludeFilters.add(0,excludeFilter);  
}  

至于过滤器为什么会在扫描过程中起作用,我们在后面分析扫描实现的时候再深入研究。
3.扫描Java文件
设置了相关属性以及生成了对应的过滤器后就可以进行文件的扫描了,扫描工作是有ClassPathMapperScanner类的父类ClassPathBeanDefinitionScanner的scan方法完成的。

public int scan(String... basePackages) {  
    int beanCountAtScanStart = this.registry.getBeanDefinitionCount();  

    doScan(basePackages);  

    // Register annotation config processors, if necessary.  
    if (this.includeAnnotationConfig) {  
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);  
    }  

    return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);  
}  

scan是个全局方法,扫描工作通过
[java] view plain copy 在CODE上查看代码片派生到我的代码片
doScan(basePackages);
委托给了doScan方法,同时,还包括了includeAnnotationConfig属性的处理,AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);代码主要是完成对于注解处理器的简单注册,我们下面主要分析下扫描功能的实现 。

public Set<BeanDefinitionHolder> doScan(String... basePackages) {  
  Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);  

  if (beanDefinitions.isEmpty()) {  
    //没有扫描到任何文件发出警告  
    logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");  
  } else {  
    for (BeanDefinitionHolder holder : beanDefinitions) {  
      GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();  

      if (logger.isDebugEnabled()) {  
        logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName()   
            + "' and '" + definition.getBeanClassName() + "' mapperInterface");  
      }  

      // the mapper interface is the original class of the bean  
      // but, the actual class of the bean is MapperFactoryBean  
      //开始构造MapperFactoryBean类型的bean.  
      definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName());  
      definition.setBeanClass(MapperFactoryBean.class);  

      definition.getPropertyValues().add("addToConfig", this.addToConfig);  

      boolean explicitFactoryUsed = false;  
      if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {  
        definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));  
        explicitFactoryUsed = true;  
      } else if (this.sqlSessionFactory != null) {  
        definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);  
        explicitFactoryUsed = true;  
      }  

      if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {  
        if (explicitFactoryUsed) {  
          logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");  
        }  
        definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));  
        explicitFactoryUsed = true;  
      } else if (this.sqlSessionTemplate != null) {  
        if (explicitFactoryUsed) {  
          logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");  
        }  
        definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);  
        explicitFactoryUsed = true;  
      }  

      if (!explicitFactoryUsed) {  
        if (logger.isDebugEnabled()) {  
          logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");  
        }  
        definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);  
      }  
    }  
  }  

  return beanDefinitions;  
}  

此时,虽然还没有完成介绍到扫描的过程,但是我们也应该理解了Spring中对于自动扫描的注册,声明MapperScannerConfigurer类型的bean目的是不需要我们对于每个接口都注册一个MapperFactoryBean类型的对应的bean,但是,不再配置文件中注册并不代表这个bean不存在,而是在扫描的过程中通过编码的方式动态注册。实现过程我们在上面的函数中可以看得非常清楚 。

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {  
    Assert.notEmpty(basePackages, "At least one base package must be specified");  
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();  
    for (String basePackage : basePackages) {  
        //扫描basePackage路径下的java文件  
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);  
        for (BeanDefinition candidate : candidates) {  
            //解析scope属性  
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);  
            candidate.setScope(scopeMetadata.getScopeName());  
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);  
            if (candidate instanceof AbstractBeanDefinition) {  
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);  
            }  
            if (candidate instanceof AnnotatedBeanDefinition) {  
                //如果是AnnotationBeanDefinition类型的bean需要检测下常用注解如:Primary,Lazy等。  
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);  
            }  
            //检测当前bean是否已经注册  
            if (checkCandidate(beanName, candidate)) {  
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);  
                //如果当前bean是用于生成代理的bean那么需要进一步处理  
                definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);  
                beanDefinitions.add(definitionHolder);  
                registerBeanDefinition(definitionHolder, this.registry);  
            }  
        }  
    }  
    return beanDefinitions;  
}  
public Set<BeanDefinition> findCandidateComponents(String basePackage) {  
    Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();  
    try {  
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +  
                resolveBasePackage(basePackage) + "/" + this.resourcePattern;  
        Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);  
        boolean traceEnabled = logger.isTraceEnabled();  
        boolean debugEnabled = logger.isDebugEnabled();  
        for (Resource resource : resources) {  
            if (traceEnabled) {  
                logger.trace("Scanning " + resource);  
            }  
            if (resource.isReadable()) {  
                try {  
                    MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);  
                    if (isCandidateComponent(metadataReader)) {  
                        ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);  
                        sbd.setResource(resource);  
                        sbd.setSource(resource);  
                        if (isCandidateComponent(sbd)) {  
                            if (debugEnabled) {  
                                logger.debug("Identified candidate component class: " + resource);  
                            }  
                            candidates.add(sbd);  
                        }  
                        else {  
                            if (debugEnabled) {  
                                logger.debug("Ignored because not a concrete top-level class: " + resource);  
                            }  
                        }  
                    }  
                    else {  
                        if (traceEnabled) {  
                            logger.trace("Ignored because not matching any filter: " + resource);  
                        }  
                    }  
                }  
                catch (Throwable ex) {  
                    throw new BeanDefinitionStoreException(  
                            "Failed to read candidate component class: " + resource, ex);  
                }  
            }  
            else {  
                if (traceEnabled) {  
                    logger.trace("Ignored because not readable: " + resource);  
                }  
            }  
        }  
    }  
    catch (IOException ex) {  
        throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);  
    }  
    return candidates;  
}  

findCandidateComponents方法根据传入的包路径信息并结合类文件路径拼接成文件的绝对路径,同时完成了文件的扫描过程并且根据对应的文件生成了对应的bean,使用ScannedGenericBeanDefinition类型的bean承载信息,bean中值记录了resource和source信息。这里,我们更感兴趣的是isCandidateCompanent(metadataReader),此句代码用于判断当前扫描的文件是否符合要求,而我们之前注册的过滤器也是在此派上用场的。

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {  
    for (TypeFilter tf : this.excludeFilters) {  
        if (tf.match(metadataReader, this.metadataReaderFactory)) {  
            return false;  
        }  
    }  
    for (TypeFilter tf : this.includeFilters) {  
        if (tf.match(metadataReader, this.metadataReaderFactory)) {  
            AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();  
            if (!metadata.isAnnotated(Profile.class.getName())) {  
                return true;  
            }  
            AnnotationAttributes profile = MetadataUtils.attributesFor(metadata, Profile.class);  
            return this.environment.acceptsProfiles(profile.getStringArray("value"));  
        }  
    }  
    return false;  
}  
随笔记:SpringBoot引入第三方jar包并包扫描问题 -------------springboot打包部署---------------------------------------------------------------------------------------------------------------------分割线,下面是SpringBoot打包东西-------------------------------------------3.解决办法,如果A子模块包依赖了B子模块包,在B子模块的pom文件,加入。 阅读详情

相关推荐

spring和mybatis的dao层接口调用的原理探究

首先我们来看看mybatis简单的使用方法. 我们需要配置一个UserDao.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" &...

dressrosa 3817

MapperScannerConfigurer

Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring Mybatis在与Spring集成的时候可以配置MapperFactoryBean来生成Mapper接口的代理. 例如   MapperFactoryBean 创建的代理类实现了 UserMapper 接口,并且注入到应用程

我是谁 2944

Linux ELF文件解析:从file到readelf的完整工具链指南

ELF(可执行与可链接格式)是Linux系统中二进制文件的标准格式,定义了程序加载、内存布局和元数据组织方式。其核心原理在于通过程序头表描述执行视图、节区头表描述链接视图,实现代码与数据的结构化存储。这一格式的技术价值在于为程序调试、安全审计和性能优化提供了底层支持,尤其在动态链接、符号解析和内存保护机制中发挥关键作用。在应用场景上,系统管理员依赖ELF分析工具解决库依赖问题,安全研究员通过检查安全属性评估漏洞风险,开发者则利用反汇编进行代码调试。本文聚焦于file、readelf、objdump等工具链的

weixin_42691065的博客 635

MapperScannerConfigurer的作用

MyBatis的一大亮点就是可以不用dao层的实现类,而我们知道在开发中service层需要调用dao层,如果没有dao的实现类,Spring如何为Service注入dao的实例呢? Mybatis在与Spring集成的时候可以配置MapperFactoryBean来生成Mapper接口的代理。MapperFactoryBean的出现为了代替手工使用SqlSessionDaoSupport或SqlSessionTemplate编写数据访问对象(DAO)的代码,使用动态代理实现。比如下面这个官方文档中的配置:

ZaynFox的博客 9359

【Python】SUMO + Python 联合仿真平台

强化学习的核心思想是让智能体 (Agent) 通过与环境 (Environment) 的交互来学习如何做出最优决策,以最大化累积奖励 (Cumulative Reward)。在交通场景中,智能体可以是交通信号控制器、自动驾驶车辆或交通管理中心,环境则是 SUMO 模拟的交通路网,奖励则与交通效率、安全、环保等目标相关。交通系统本质上是动态的、随机的、高度复杂的系统,传统的基于规则或模型的优化方法在面对不断变化的需求和突发事件时,往往显得力不从心。强化学习的优势在于:在交通领域,强化学习已经被广泛应用于:为了

宅男很神经 1989

正点原子ATK-LORA-01无线串口代码移植+STM32F103C8T6(标准库)

目录 一、ATK-LORA-01无线串口资料 二、代码移植 1.分析 (1)usart3(也可以是其他的串口)用于接收数据的串口 usart.h (2)time3(也可以是其他的定时器)用于时序的设置 (3)lora.c 三、演示 1.主机(发送方) (1)主机接线 (2)主机代码(发送方) (3)主机实物 插上无线串口通电即可发送​ 2.从机(接收方) (1)从机接线(LORA与主机相同) (2)从机代码(接收方) (3)从机实物 接上TTL和LORA并通电即...

m0_56942354的博客 8968

4、MapperScannerConfigurer

这节的MapperScannerConfigurer与spring耦合性比较强,所以如果遗忘了知识点的,请移步到spring源码分析系列文章中复习下 虽然可以不配置扫描器,但是通常我们在项目中还是会去配置扫描器,配置如下: <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <prope...

zhen_hong的博客 1325

免费搞定DWG转DXF:ODA File Converter保姆级配置指南(附常见报错解决)

本文详细介绍了如何使用ODA File Converter免费工具实现DWG到DXF的格式转换,包括环境配置、命令行参数解析、编程集成方案及常见问题解决。特别针对网络访问异常、参数配置等实际痛点提供应对策略,帮助用户高效完成工程设计文件的格式转换。

weixin_29291185的博客 6019

Springboot + Mybatis 接口编程中dao 层接口没有注解和<bean> 为什么能被实例化为bean

Springboot + Mybatis 接口编程中dao 层接口没有注解和 为什么能被实例化为bean Mybatis 接口编程中dao 层接口没有注解和 为什么能被实例化为bean?? 相信不少人有过这个疑问,我自己带着这个疑问好久了!我自己写dao 层接口都是自己加上@Component这个注解,但是项目组的其他同事不写的情况也可以正常注入?带着这个疑问我一点一点查找资料。最终发现 MapperScannerConfigurer 帮我们做了实例化bean的工作。 在Spring配置Mybatis的文件

maying0124的博客 2051

模型算力需求估算

(Billion Parameters,简称B)和训练/推理的计算任务复杂度,结合硬件计算能力(例如每秒浮点运算次数,FLOPS)来估算。以下是详细的方法和公式说明,以及实际的计算示例。算力需求的估算依赖于参数量、模型架构及硬件性能,结合训练/推理场景的特定要求来计算。通过上述公式和示例,我们可以定量分析不同任务的算力需求,并合理配置硬件资源以优化运行效率。结论:推理任务相对较轻,单台H100可以在30秒内完成此任务。推理算力需求一般远低于训练,因为只需要执行前向传播。,可以将训练时间缩短到约。

形上得其象,形下合于数;阴阳自济,玄理自明。 8954

ONVIF协议简介与协议测试工具使用详解

Onvif协议及协议测试工具使用详解

dvlinker的技术专栏 3万+

使用MyBatis时为什么Dao层不需要@Repository

问题Service层注入Dao时, Intellij 总会以红色波浪线提示我们 12@Autowiredprivate UserDao userDao; Could not autowire. No beans of ‘UserDao’ type found.Checks autowiring problems in a bean class. 尽管我...

hehyyoulan的博客 6383

C#解析基恩士(KEYENCE)PLC数据:KV协议通信与实时监控实现

KV协议是基恩士PLC使用的一种专用通信协议,通常用于与上位机进行数据交换。KV协议通过RS-232C、RS-485、Ethernet等接口与上位机通信,支持多种数据类型的读写,包括但不限于位、字、双字、浮点数等。简洁易用:KV协议的通信格式简单,易于实现。支持多种数据类型:支持位数据、字数据、定长字符串等。高效实时性:能够提供较高的实时数据交换性能,适合实时监控应用。本文介绍了如何通过C#与基恩士KV系列PLC进行通信,实现数据的解析和实时监控功能。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1807

彻底搞懂使用MyBatis时为什么Dao层不需要@Repository

问题 Service层注入Dao时, Intellij 总会以红色波浪线提示我们 1 2 @Autowired private UserDao userDao; Could not autowire. No beans of ‘UserDao’ type found. Checks autowiring problems in a bean c...

liinux-Talk is cheap,show me the code. 6001

【算法】克里金kriging参数值预测模型

模型中特征值2个,目标值1个,data数据集如图所示。搭建kriging参数值预测模型。

weixin_48618536的博客 5059

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Mybatis 接口编程中dao 层接口不需要注解和<bean> 为什么能被实例化为bean

Mybatis 接口编程中dao 层接口没有注解和 为什么能被实例化为bean?? 相信不少人有过这个疑问,我自己带着这个疑问好久了!我自己写dao 层接口都是自己加上@Repository这个注解,但是项目组的其他同事不写的情况也可以正常注入?带着这个疑问我一点一点查找资料。最终发现 MapperScannerConfigurer 帮我们做了实例化bean的工作。 在Spring配置Myba...

iceloop的博客 1057

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

springboot+mybatis使用注解方式,出现错误创建dao层bean

今天项目里面的其他控制器都使用jpa注解进行数据的查询。我写的功能模块里面的控制器,要求不用jpa查询数据,使用mybatis的注解查询。在springboot项目中,写完后启动项目发现错误创建dao层bean,找了很久不知道为啥,最后发现项目中引入的jar包有问题,原来引入的jar包为mybatis和mybatis-spring的。修改成mybatis-spring-start后,重新启动项目,...

Coffee的博客 3897

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

mybatis-spring注解标识dao层

在xml文件中配置MapperScannerConfigurer这个bean的属性,启动spring的时候扫描自定义的@Repository注解

lzf的博客 3078

SSM项目的dao层接口不加@Repository也不报错,能够实例化为bean?Could not autowire. No beans of ‘XxxDao‘ type found错误

为什么dao/mapper层接口不写注解@Repository也能被实例化为bean? 因为在spring整合mybatis的时候,在spring的核心配置文件applicationContext.xml中,配置了MapperScannerConfigurer。 `MapperScannerConfigurer`的作用就是让它扫描指定的包,然后由容器自动批量地创建映射器,减少代码(就不需要在dao/mappper接口上加注解@Repository了) <!-- 配置映射文件扫描器 : IPers

Java小皮孩 3578

dao层注解@Repository在idea环境下无法进行bean注册问题

问题:在idea环境下,注解@Repository注册dao曾bean的时候显示无法注入 @Repository public interface BloggerDao { //查询博主信息 Blogger getBloggerData(); //通过用户名查询博主信息 Blogger getBloggerDataByName(String name); } @Service p...

debug 4070

springBoot 中关于dao层的三个注解 @Repository @Mapper @MapperScan @Component 的区别和理解

原文链接:https://blog.youkuaiyun.com/u013158317/article/details/104006164 我提取的精华: 总结 @Mapper 一定要有,否则 Mybatis 找不到 mapper。 @Repository 可有可无,可以消去依赖注入的报错信息。 @MapperScan 可以替代 @Mapper。 1、@Mapper @Mapper 是 Mybatis 的注解,和 Spring 没有关系,@Repository 是 Spring 的注解,用于声明一个 Bean。 在 S

优快云_RLZ的博客 1万+

Spring Dao层@Repository 与 @Mapper

使用注解的方式开发Dao层的时候,常常会混淆这两个注解,不知道怎么添加,这里做个记录。 总结 @Mapper 一定要有,否则 Mybatis 找不到 mapper。 @Repository 可有可无,可以消去依赖注入的报错信息。 @MapperScan 可以替代 @Mapper。 1 - @Mapper @Mapper 是 Mybatis 的注解,和 Spring 没有关系,@...

u013158317的博客 3725

Springboot mybitas dao层使用的注解

@Mapper 使用@Mapper注解要定义成一个接口interface 作用:1.使用@Mapper将NewsDAO接口交给Spring进行管理 2.不用写Mapper映射文件(XML) 3.为这个NewsDAO接口生成一个实现类,让别的类进行引用 @param 当有多个参数的时候使用@param注解. 在mapper.xml中使用的时候,#{对象别名.属性名},如#{user.u...

qq_38444415的博客 1万+

SpringBoot集成MyBatis——逆向工程生成实体Bean、映射文件、DAO接口

1.SpringBoot集成MyBatis 1.1添加mybatis依赖,MySQL驱动 pom <!--MySQL驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> &l

qq_45896330的博客 7484
上一篇: org.apache.ibatis.binding.BindingException: Mapper method 'com.zbiti.alarm.dao.AlarmDao.queryTest at
下一篇: 在线api汇总,应该对你开发有帮助
差点九零后
博客等级 码龄15年 2粉丝 8原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值