6. Spring:Java注解技术详解

本文深入解析Java注解技术,包括注解的基本概念、原理、应用场合及自定义注解的创建方法。涵盖标准注解如Override、Deprecated、SuppressWarnings,以及元注解@Target、@Retention、@Documented、@Inherited的详细使用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

6. Spring:Java注解技术详解

自定义注解示例:https://blog.youkuaiyun.com/wangpengzhi19891223/article/details/78131137/

  1. Java注解技术基本概念

    Annotation是Java5开始引入的新特征。中文名称一般叫注解。它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联

    • 原理

      注解其实是一种接口,通过Java反射机制相关的API来访问注解的信息。

      注解不会影响程序的运行

    • 和接口的区别

      • 注解是使用的关键字@interface而不是interface,是继承了java.lang.annotation.interface

        并非声明了一个接口

      • 注解类型方法定义是受限制的,独特的。

      • 可以定义常量

    • 应用场合

      • 工具类,工具框架中
  2. Java标准注解

    • Override

      标注重载了父类的方法(如果标注在不是覆盖父类的方法上,会编译错误)

    • Deprecate

      标注此方法已过时

    • SuppressWarnings

      屏蔽警告

      @SuppressWarnings(value={"unchecked","fallthrough"})
      public void test()   { /* method body   */ }
      
      @SuppressWarnings({"unchecked","fallthrough"})
      public void test()   { /* method body   */ }
      
      @SuppressWarnings("unchecked")
      public void test()   { /* method body   */ }
      
      
  3. Java元注解

    元注解:负责注解其他注解的注解

    Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明,Java5.0定义的元注解有以下四种类型:

    • @Target

      @Target主要作用是用于描述注解的使用范围,即被描述的注解可以用在什么地方

      • 作用范围

        • CONSTRUCTOR
        • FIELD
        • LOCAL_VARIABLE
        • METHOD
        • PACKAGE
        • PARAMETER
        • TYPE
      • 示例

        @Target(ElementType.TYPE)
        public @interface Table {
            public String tableName() default "className";
        }
        // Table注解可以用来注解类,接口,类型,枚举声明
        
        
        @Target(ElementType.FIELD)
        public @interface NoDBColumn {     }
        // NoDBColumn仅用来类的成员变量
        
    • @Retention

      Retention主要表示需要在什么级别保存该注释信息,用于描述注解的生命周期

      • 描述生命周期(注解在什么范围内有效)

        • SOURCE:源文件中是有效的,源文件中是保留的
        • CLASS:CLASS文件中是有效的
        • RUNTIME:在运行时有效,运行时保留
      • 示例

        @Target(ElementType.FIELD)
        @Retention(RetentionPolicy.RUNTIME)
        public @interface Column {
            public String name() default "fieldName";
            public String setFuncName() default "setField";
            public String getFuncName() default "getField"; 
            public boolean defaultDBValue() default false;
        }
        
    • @Documented

      @Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化

      • 示例

        @Target(ElementType.FIELD)
        @Retention(RetentionPolicy.RUNTIME)
        @Documented
        public @interface Column {
            public String name() default "fieldName";
            public String setFuncName() default "setField";
            public String getFuncName() default "getField"; 
            public boolean defaultDBValue() default false;
        }
        
        
    • @Inherited

      @Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类:

      • 示例

        @Inherited
        public @interface Greeting {
            public enum FontColor{ BULE,RED,GREEN};
            String name();
            FontColor fontColor() default FontColor.GREEN;
        }
        
  4. Java自定义注解

    • 步骤

      • 通过@interface关键字声明注解名称、注解成员属性等

      • 使用Java内置四个元注解对自定义标注的功能和范围进行约束

        自定义注解的格式: public @interface 注解名 { 定义体 }

    • 支持的数据类型

      • 所有基本数据类型
      • String 类型
      • Class 类型
      • enum 类型
      • Annotation 类型
      • 以上所有类型的数组
    • 自定义注解定义:

      @Target(ElementType.FIELD)
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      public @interface FruitName {
          String value() default "";
      }
      
    • 自定义注解的使用

      public class Apple {
          @FruitName("Apple")
          private String appleName;
          // ……
      }
      
      
  5. 注解元素默认值

    注解元素的默认值:注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null:

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface FruitProvider {
    	//供应商编号
    	public int id() default -1;
    	//供应商名称
    	public String name() default "";
    	//供应商地址
    	public String address() default "";
    }
    
    
2025-07-16T08:39:46.554+08:00 ERROR 16124 --- [takeout system] [ main] o.s.boot.SpringApplication : Application run failed org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'userMapper' defined in file [E:\IDEA\takeoutsystem\target\classes\com\example\takeoutsystem\mapper\UserMapper.class]: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:864) ~[spring-beans-6.2.8.jar:6.2.8] at org.springframework.beans.factory.support.AbstractBeanFactory.getType(AbstractBeanFactory.java:745) ~[spring-beans-6.2.8.jar:6.2.8] at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAnnotationOnBean(DefaultListableBeanFactory.java:817) ~[spring-beans-6.2.8.jar:6.2.8] at org.springframework.boot.sql.init.dependency.AnnotationDependsOnDatabaseInitializationDetector.detect(AnnotationDependsOnDatabaseInitializationDetector.java:36) ~[spring-boot-3.4.7.jar:3.4.7] at org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer$DependsOnDatabaseInitializationPostProcessor.detectDependsOnInitializationBeanNames(DatabaseInitializationDependencyConfigurer.java:152) ~[spring-boot-3.4.7.jar:3.4.7] at org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer$DependsOnDatabaseInitializationPostProcessor.postProcessBeanFactory(DatabaseInitializationDependencyConfigurer.java:115) ~[spring-boot-3.4.7.jar:3.4.7] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:363) ~[spring-context-6.2.8.jar:6.2.8] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:197) ~[spring-context-6.2.8.jar:6.2.8] at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:791) ~[spring-context-6.2.8.jar:6.2.8] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:609) ~[spring-context-6.2.8.jar:6.2.8] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.4.7.jar:3.4.7] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) ~[spring-boot-3.4.7.jar:3.4.7] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) ~[spring-boot-3.4.7.jar:3.4.7] at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) ~[spring-boot-3.4.7.jar:3.4.7] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) ~[spring-boot-3.4.7.jar:3.4.7] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) ~[spring-boot-3.4.7.jar:3.4.7] at com.example.takeoutsystem.TakeoutApplication.main(TakeoutApplication.java:11) ~[classes/:na] 进程已结束,退出代码为 1 这是因为上面
最新发布
07-17
<think>我们遇到了一个Spring Boot启动失败的问题,错误信息如下: ``` 2025-07-16T08:39:46.554+08:00 ERROR 16124 --- [takeout system] [ main] o.s.boot.SpringApplication : Application run failed org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'userMapper' defined in file [E:\IDEA\takeoutsystem\target\classes\com\example\takeoutsystem\mapper\UserMapper.class]: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String ... ``` 错误原因:在名为'userMapper'的bean定义中,属性'factoryBeanObjectType'的值类型无效,期望的类型是java.lang.String,但实际可能是其他类型。 根据堆栈信息,问题发生在`AbstractAutowireCapableBeanFactory.getTypeForFactoryBean`方法中。这通常与Spring的bean创建过程有关,特别是当bean是一个工厂bean(FactoryBean)时。 可能的原因: 1. 可能是在使用MyBatis时,Mapper接口被Spring错误地当作普通bean处理,而不是通过MyBatis的`MapperFactoryBean`来创建。通常,我们使用`@MapperScan`来扫描Mapper接口,这样Spring会为每个Mapper接口创建一个`MapperFactoryBean`,然后通过这个工厂bean来生成Mapper的代理对象。 2. 另一个可能的原因是配置问题,比如没有正确配置MyBatis的`SqlSessionFactory`,或者`@MapperScan`注解没有正确使用。 3. 还有可能是版本兼容性问题,但这里使用的是Spring Boot 3.4.7和MyBatis Spring Boot Starter,需要确保版本匹配。 解决方案: 1. 确保在Spring Boot主类上(或者配置类上)添加了`@MapperScan`注解,指定Mapper接口所在的包。例如: ```java @SpringBootApplication @MapperScan("com.example.takeoutsystem.mapper") public class TakeoutApplication { public static void main(String[] args) { SpringApplication.run(TakeoutApplication.class, args); } } ``` 2. 检查pom.xml中是否引入了MyBatis Spring Boot Starter依赖,并且版本与Spring Boot兼容。例如: ```xml <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.3</version> <!-- 请根据Spring Boot版本选择兼容的版本 --> </dependency> ``` 注意:Spring Boot 3.x需要MyBatis Spring Boot Starter 3.x版本。 3. 检查Mapper接口是否被正确标注了`@Mapper`注解(如果使用`@MapperScan`则可以不标注,但若没有`@MapperScan`,每个Mapper接口都需要标注`@Mapper`)。不过,通常推荐使用`@MapperScan`。 4. 检查Mapper接口是否被错误地添加了`@Component`或其他Spring注解?Mapper接口应该只是一个接口,不需要其他注解(除了MyBatis的注解如`@Select`等)。 5. 检查配置文件中是否有关于MyBatis的配置,比如`mybatis.mapper-locations`是否指向了正确的mapper.xml文件位置(如果有XML文件的话)。 6. 如果使用了多个数据源或特殊配置,可能需要自定义`SqlSessionFactoryBean`,但需要确保正确配置。 由于错误信息中提到了`factoryBeanObjectType`属性类型错误,可能是Spring在尝试将`UserMapper`接口当作一个普通的FactoryBean来处理,但期望的`factoryBeanObjectType`应该是`Class<?>`类型,而实际可能是其他类型。这通常是因为没有正确配置MyBatis,导致Spring无法识别这是一个MyBatis的Mapper工厂bean。 因此,重点检查`@MapperScan`和依赖。 如果以上步骤都没有解决问题,可以尝试清理和重新构建项目(比如删除target目录,重新运行`mvn clean install`或Gradle的相应命令)。 下面是一个示例的配置: 1. 主类配置: ```java package com.example.takeoutsystem; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("com.example.takeoutsystem.mapper") public class TakeoutApplication { public static void main(String[] args) { SpringApplication.run(TakeoutApplication.class, args); } } ``` 2. pom.xml依赖(示例): ```xml <dependencies> <!-- 其他依赖 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> <!-- 数据库驱动,比如MySQL --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> </dependencies> ``` 3. 确保Mapper接口在`com.example.takeoutsystem.mapper`包下,例如: ```java package com.example.takeoutsystem.mapper; import org.apache.ibatis.annotations.Mapper; @Mapper // 如果使用了@MapperScan,这个注解可以省略,但建议保留或者二选一 public interface UserMapper { // 方法定义 } ``` 4. 在application.properties或application.yml中配置数据源和MyBatis(如果需要): ```properties spring.datasource.url=jdbc:mysql://localhost:3306/takeout?serverTimezone=UTC spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # 如果需要指定mapper.xml文件的位置(如果使用XML方式) mybatis.mapper-locations=classpath:mapper/*.xml ``` 如果问题仍然存在,请检查是否有其他配置干扰,比如是否自定义了`SqlSessionFactory`?如果有,请确保其正确性。 由于错误信息指向了`UserMapper`,所以请仔细检查`UserMapper`的定义和相关的配置。 希望这些步骤能帮助你解决问题。 §§相关问题§§: 1. 如何正确配置MyBatis与Spring Boot的集成? 2.Spring Boot中,使用MyBatis时有哪些常见的配置错误? 3. 如何解决Spring Boot启动时Bean创建失败的问题? 4. 如何自定义MyBatis的SqlSessionFactory?</think>### 问题分析 根据错误日志,Spring Boot应用启动失败的原因是`userMapper`的Bean定义无效。核心错误信息是: ``` Invalid bean definition with name 'userMapper'... Invalid value type for attribute 'factoryBeanObjectType': java.lang.String ``` 这表明Spring在尝试创建`userMapper` Bean时,遇到了类型不匹配的问题。具体来说,`factoryBeanObjectType`属性期望一个`Class`类型,但实际获取到的是`String`类型。 ### 解决方案 #### 1. 检查Mapper接口注解 确保Mapper接口正确使用了`@Mapper`注解(或`@Repository`),且没有错误添加其他注解: ```java // 正确示例 package com.example.takeoutsystem.mapper; import org.apache.ibatis.annotations.Mapper; @Mapper // ✅ 关键注解 public interface UserMapper { // 方法定义 } ``` #### 2. 检查Mapper扫描配置 在Spring Boot主类或配置类中添加`@MapperScan`扫描Mapper接口: ```java package com.example.takeoutsystem; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("com.example.takeoutsystem.mapper") // ✅ 指定Mapper包路径 public class TakeoutApplication { public static void main(String[] args) { SpringApplication.run(TakeoutApplication.class, args); } } ``` #### 3. 验证依赖配置 在`pom.xml`中确保包含正确的MyBatis依赖: ```xml <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.3</version> <!-- 匹配Spring Boot 3.x --> </dependency> ``` #### 4. 检查XML映射文件(如果使用) 若使用XML映射文件,确保路径配置正确(`application.properties`): ```properties # 正确配置XML路径 mybatis.mapper-locations=classpath*:mapper/**/*.xml ``` #### 5. 清理并重建项目 执行Maven清理和重新编译: ```bash mvn clean install ``` ### 错误原因详解 1. **factoryBeanObjectType类型不匹配** Spring期望该属性为`Class<?>`类型,但实际获取到`String`。通常是因为: - Mapper接口未被正确识别为MyBatis组件 - 缺少`@MapperScan`导致Spring尝试用错误方式创建Bean 2. **常见触发场景** - 忘记添加`@Mapper`或`@MapperScan` - Mapper接口被错误添加`@Component`或`@Service` - MyBatis依赖版本不兼容(如Spring Boot 3.x使用MyBatis 2.x) ### 验证修复 修复后启动日志应显示Mapper被正确注册: ``` 2025-07-16 INFO [main] o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'userMapper' ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值