[problem analysis] an error is reported when injecting the service layer bindingexception



@Mapperscan scans the root path of the project. The project contains the service layer interface demoservice and implementation class demoserviceimpl. Injection:

private DemoService demoService;

When demoservice. Insert() is called, an error is reported

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): xxx.service.DemoService.insert


The interrupt point is to view the type of demoservice, which is a mapperproxy. It seems that mybatis failed to find the mapper.xml corresponding to demoservice and reported an error?

And other placesDemoServiceImplInjection is normal. Understand the injection rules of @ Autowired. It is in the same type of interfaceWhen there are multiple implementations, priority is given to inject by attribute name, and only one implementation is injected by type.。 It seems that the reason is that mybatis has registered all interfaces under basepackages as mapperproxy.


  1. @Mapperscan’s basepackages path is only specified to the mapper layer
  2. @Autorwired injected property name plus impl or @ qualifier

Mapper registration process

  1. Enter @ mapperscan, and a configuration class mapperscannerregistrar is introduced

    public @interface MapperScan {
  2. After setting the properties in mapperscan annotation in mapperscannerregister, enter classpathmapperscanner scan bean

      public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //Set annotation properties
        //Registration filter, not here
        //Scan bean
  3. ClassPathMapperScanner calls the doScan method of the parent class to scan the beanDefinition under the basePackages path, then calls the processBeanDefinitions method to traverse the beanDefinition obtained, sets beanClass to MapperFactoryBean, and sets the constructor parameter to the interface class that is actually scanned.

      private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
        GenericBeanDefinition definition;
        for (BeanDefinitionHolder holder : beanDefinitions) {
          definition = (GenericBeanDefinition) holder.getBeanDefinition();
          if (logger.isDebugEnabled()) {
            logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() 

      // the mapper interface is the original class of the bean
      // but, the actual class of the bean is MapperFactoryBean
      //Interface class after construction parameter setting
      definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); // issue #59
      //Beanclass set to mapperfactorybean
  1. Mapperfactorybean implements spring’s factorybean and inherits mybatis’s sqlsessiondaosupport. The former is used to provide the function of getting bean instances and the latter is used to get sqlsessions. Its construction parameter mapperinterface is the above interface class, which is used to obtain the actual mapperproxy according to the interface later. That is to say, mapper is not directly registered in mybatis, but registers a mapperfactorybean. When using it, mapperproxy is obtained from sqlsession through its GetObject method

    //Interface class passed in during construction
      public MapperFactoryBean(Class<T> mapperInterface) {
        this.mapperInterface = mapperInterface;
      //Get mapperproxy on injection
      public T getObject() throws Exception {
        return getSqlSession().getMapper(this.mapperInterface);

Recommended Today

Python basics Chinese series tutorial · translation completed

Original: Python basics Python tutorial Protocol: CC by-nc-sa 4.0 Welcome anyone to participate and improve: a person can go very fast, but a group of people can go further. Online reading Apache CN learning resources catalog introduce Seven reasons to learn Python Why Python is great Learn Python introduction Executing Python scripts variable character string […]