从入门到精通:Spring基础注解的全面解析

简介: 从入门到精通:Spring基础注解的全面解析


Spring 的这些基础注解仅仅是简化了 XML 的配置,但是并不能替代 XML。Spring 使用注解后是如何进行解耦的呢(注解都写死在代理里)?其实 Spring 在应用注解开发的时候,如果对注解不满意,还是可以通过 Spring 的配置文件(XML)进行覆盖的。

想要应用 Spring 注解进行开发,还需要进行如下配置,告知 Spring 扫描对应包下的注解。

<!-- 配置扫描包 -->
<context:component-scan base-package="world.xuewei"/>

对象创建相关

@Component

替换原来的 标签,将一个类声明为组件,通常是指那些没有明显角色的类。

@Component
public class Account implements Serializable {

就相当于如下的 XML 配置:

<bean id="account" class="world.xuewei.entity.Account"/>

@Component 注解提供了默认的 id 属性,使用类名的首单词首字母小写的方式,即 Account -> accountUserService -> userService。原来 bean 标签的 class 属性,就可以通过反射的方式获取类的全限定类名。

@Component 也可以手动指定 id 属性,如下:

@Component("acc")
public class Account implements Serializable {

如果想要在 XML 中覆盖注解配置,可以在配置文件中配置 bean,要求 bean 的 id 和 class 都需要和注解的配置一致,进而可以在 bean 标签的进行注入配置等。

<bean id="acc" class="world.xuewei.entity.Account">
    <property name="id" value="1"/>
</bean>

@Component 的衍生注解

  1. @Repository:将 DAO 类声明为 Spring Bean,用于数据库访问层。
  2. @Service:将 Service 类声明为 Spring Bean,用于业务逻辑层。
  3. @Controller:将 Controller 类声明为 Spring Bean,用于 MVC 控制器层。

这些衍生注解的用法细节和 @Component 是一模一样的。只不过是换了个更有针对性的名字。

注意:Spring 整合 Mybatis 开发过程中,不使用 @Component 和 @Repository。

@Scope

@Scope 注解用于指定 Spring 管理的 Bean 的作用域(Scope),即控制 Bean 的生命周期和实例化方式。通过 @Scope 注解,你可以将一个类或方法标记为一个 Spring Bean ,并指定其作用域。

在 Spring 中,常用的作用域包括以下几种:

  1. singleton(默认):每个 Spring 容器中只存在一个 Bean 实例。无论有多少次请求,都返回同一个 Bean 实例。
  2. prototype:每次请求都会创建一个新的 Bean 实例。每次使用 getBean() 方法获取该 Bean 时,都会得到一个全新的实例。
  3. request:每个 HTTP 请求都会创建一个新的 Bean 实例。当请求结束后,Bean 实例将被销毁。
  4. session:每个 HTTP 会话(Session)都会创建一个新的 Bean 实例。当会话结束后,Bean 实例将被销毁。
@Component
@Scope("prototype")
public class MyBean {
    // ...
}

注意:如果不添加 @Scope 注解,那么默认这个 Bean 就是单例的 Singleton。

@Lazy

@Lazy 是 Spring 框架中的一个注解,用于延迟加载(Lazy Loading)Bean 实例。当一个 Bean 被标记为 @Lazy 时,它将在第一次使用时才会被初始化,而不是在应用启动时就创建。

使用 @Lazy 注解可以提高应用的性能和资源利用率,特别是在存在大量复杂或耗时的 Bean 初始化过程时。通过延迟加载,可以避免在启动阶段创建所有的 Bean 实例,从而加快应用的启动速度。

例如,假设有一个名为 MyBean 的类,我们可以将其标记为 @Lazy

@Component
@Lazy
public class MyBean {
    // ...
}

在这种情况下,当 Spring 上下文初始化时,不会立即创建 MyBean 的实例。而是在第一次访问该 Bean 时才进行初始化。

注意:@Lazy 注解只针对单实例(@Scope("singleton")) Bean 生效。当 @Scope 不为 singleton 时,指定 @Lazy 无意义。

生命周期相关

以下的两个注解并不是 Spring 提供的,而是 JSR(JavaEE 规范)520 提供,Spring 做了很好的兼容。

@PostConstruct

当一个 Bean 被标记了 @PostConstruct 注解时,在该 Bean 的依赖注入完成后,容器会自动调用被注解的方法。这个方法可以用来执行一些初始化操作,例如初始化成员变量、建立连接、加载数据等。

使用 @PostConstruct 注解的方法需要满足以下条件:

  1. 方法不能有任何参数。
  2. 方法的返回类型必须为 void
  3. 方法不能抛出受检查的异常。

例如,假设有一个名为 MyBean 的类,我们可以在其中定义一个使用 @PostConstruct 注解的方法:

@Component
public class MyBean {
    @PostConstruct
    public void init() {
        // 初始化操作
    }
}

需要注意的是,@PostConstruct 注解通常与依赖注入(如 @Autowired)一起使用,以确保依赖关系已经注入完成后再执行初始化操作。

@PreDestroy

当一个 Bean 被标记了 @PreDestroy 注解时,在该 Bean 被销毁之前,容器会自动调用被注解的方法。这个方法可以用来执行一些清理操作,例如释放资源、关闭连接等。

使用 @PreDestroy 注解的方法需要满足以下条件:

  1. 方法不能有任何参数。
  2. 方法的返回类型必须为 void
  3. 方法不能抛出受检查的异常。

例如,假设有一个名为 MyBean 的类,我们可以在其中定义一个使用 @PreDestroy 注解的方法:

@Component
public class MyBean {
    @PreDestroy
    public void cleanup() {
        // 清理操作
    }
}

需要注意的是,@PreDestroy 注解通常与依赖注入(如 @Autowired)一起使用,以确保依赖关系已经注入完成后再执行清理操作。

注入相关

@Autowired

@Autowired 注解是 Spring 框架中用于实现依赖注入的注解之一。通过 @Autowired 注解,你可以自动将依赖的 Bean 注入到需要使用它的地方,无需手动创建和管理依赖对象。

使用 @Autowired 注解时,Spring 会根据类型进行自动装配。具体来说,当 Spring 容器中存在多个与被注入字段或方法参数类型匹配的 Bean 时,Spring 会根据一定的规则选择合适的 Bean 进行注入。如果只有一个匹配的 Bean,Spring 会直接将其注入;如果没有匹配的 Bean,将会抛出异常。

@Autowired 注解可以应用在以下位置:

  1. 字段上(直接放在成员变量上的时候,Spring 通过反射为变成进行赋值注入,不是通过 Set 方法):
@Autowired
private MyDependency myDependency;
  1. 构造函数上:
@Autowired
public MyClass(MyDependency myDependency) {
    this.myDependency = myDependency;
}
  1. Set 方法上(通过调用 Set 方法进行赋值注入):
@Autowired
public void setMyDependency(MyDependency myDependency) {
    this.myDependency = myDependency;
}

将下面的 Spring XML 配置可以转换为:

<bean id="accountService" class="world.xuewei.service.AccountServiceImpl">
    <property name="accountDao" ref="accountDao"/>
</bean>
@Repository
public class AccountDao {
    void insert(Account account){
        // ...
    }
}
@Service
public class AccountService {
    private AccountDao accountDao;
    public AccountDao getAccountDao() {
        return accountDao;
    }
    @Autowired
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
    void register(Account account) {
        accountDao.insert(account);
    }
}

@Autowired 是基于类型进行注入的,要注入的 Bean 需要是定义成员变量的相同类型、或子类、或实现类。

@Qualifier

@Qualifier 注解是 Spring 框架中用于解决依赖注入歧义性的注解。当存在多个类型相同的 Bean 时,使用 @Qualifier 注解可以指定要注入的特定 Bean。

在使用 @Autowired 进行自动装配时,如果存在多个与被注入字段或方法参数类型匹配的 Bean,Spring 无法确定要注入哪个 Bean,从而抛出异常。这时,可以结合 @Qualifier 注解来解决歧义性问题。

@Qualifier 注解可以应用在以下位置:

  1. 字段上:
@Autowired
@Qualifier("myBean")
private MyInterface myBean;
  1. 构造函数上:
@Autowired
public MyClass(@Qualifier("myBean") MyInterface myBean) {
    this.myBean = myBean;
}
  1. Set 方法上:
@Autowired
public void setMyBean(@Qualifier("myBean") MyInterface myBean) {
    this.myBean = myBean;
}

需要注意的是,@Qualifier 注解配合 @Autowired 注解使用时,要确保指定的 Bean 名称与容器中的 Bean 名称一致。通常情况下,Bean名称是通过 @Component@Service@Repository 等注解指定的,或者是根据默认的命名规则生成的。

@Resouce

@Resource 注解是 Java EE(JSR 250) 标准中用于实现依赖注入的注解之一。它可以用于注入其他组件或资源,如数据源、JMS 队列等。在 Spring 框架中,@Resource 注解也可以用于实现依赖注入。

@Autowired 注解不同的是,@Resource 注解既可以按照名称进行注入,也可以按照类型进行注入。当使用 @Resource 注解按照名称进行注入时,它会根据指定的名称在容器中查找对应的 Bean 进行注入;当使用 @Resource 注解按照类型进行注入时,它会根据指定的类型在容器中查找对应的 Bean 进行注入。

  • 使用名称注入:@Resource(name = “XXX”),此时相当于 @Autowired 和 @Qualifier 的组合,但是需要注意的是,@Resource(name = “XXX”) 如果没有匹配到指定名称的 Bean,那么会按照类型再去匹配。
  • 使用类型注入:单独使用 @Resource,此时相当于 @Autowired。

@Resource 注解可以应用在以下位置:

  1. 字段上:
@Resource(name = "myBean")
private MyInterface myBean;
  1. 构造函数上:
@Autowired
public MyClass(@Resource(name = "myBean") MyInterface myBean) {
    this.myBean = myBean;
}
  1. Set 方法上:
@Resource(name = "myBean")
public void setMyBean(MyInterface myBean) {
    this.myBean = myBean;
}

需要注意的是,@Resource 注解在按照名称进行注入时,要确保指定的 Bean 名称与容器中的 Bean 名称一致。通常情况下,Bean名称是通过 @Component@Service@Repository 等注解指定的,或者是根据默认的命名规则生成的。

@Inject

@Inject 是 Java 中的一个注解,用于进行依赖注入。它是 Java 的标准依赖注入规范(JSR 330)中定义的注解之一。

使用 @Inject 注解可以在需要依赖的地方进行注入,例如字段、构造方法、普通方法等。它可以与其他依赖注入框架(如 Spring、CDI)一起使用,也可以作为 Java 自带的依赖注入机制的一部分使用。

@Inject 的用法与 @Autowired 完全一致。都是基于类型的注入。但是我们想要使用 Inject 注解,我们还需要额外引入依赖。

<dependency>
  <groupId>javax.inject</groupId>
  <artifactId>javax.inject</artifactId>
  <version>1</version>
</dependency>

@Value

@Value 注解是 Spring 框架中用于注入值的注解。它可以用于将配置文件中的值或者直接指定的值注入(通过 ${} 符号读取)到 Bean 中的字段、方法参数或构造函数中。

定义配置文件 test.properties 内容如下:

my.property=XW

配置 Spring 加载指定配置文件:

<!-- 指定加载配置文件 -->
<context:property-placeholder location="classpath:test.properties"/>

@Value 注解可以应用在以下位置:

  1. 字段上:
@Value("${my.property}")
  1. 构造函数上:
@Autowired
public MyClass(@Value("${my.property}") String myProperty) {
    this.myProperty = myProperty;
}
  1. Set 方法上:
@Autowired
public void setMyProperty(@Value("${my.property}") String myProperty) {
    this.myProperty = myProperty;
}

注意:@Value 注解不能标记在静态属性中。如果是静态的变量,那么无法进行复制(但是不会报错)。

注意:@Value 注解 + properties 这种方式不能注入集合类型的数据。可以通过 @Value + YAML 文件的方式实现集合类型的数据的注入。

@PropertySource

在上面的 @Value 笔记中,我们需要在 Spring 的配置文件中配置加载指定的配置文件。Spring 提供了 @PropertySource 注解让我们省去配置 XML。

@Component
@PropertySource("classpath:test.properties")
public class Account implements Serializable {
    private Integer id;
    @Value("${my.property}")
    private String name;
 
    // ..
}



相关文章
|
1月前
|
数据采集 人工智能 Java
1天消化完Spring全家桶文档!DevDocs:一键深度解析开发文档,自动发现子URL并建立图谱
DevDocs是一款基于智能爬虫技术的开源工具,支持1-5层深度网站结构解析,能将技术文档处理时间从数周缩短至几小时,并提供Markdown/JSON格式输出与AI工具无缝集成。
111 1
1天消化完Spring全家桶文档!DevDocs:一键深度解析开发文档,自动发现子URL并建立图谱
|
1月前
|
安全 Java API
深入解析 Spring Security 配置中的 CSRF 启用与 requestMatchers 报错问题
本文深入解析了Spring Security配置中CSRF启用与`requestMatchers`报错的常见问题。针对CSRF,指出默认已启用,无需调用`enable()`,只需移除`disable()`即可恢复。对于`requestMatchers`多路径匹配报错,分析了Spring Security 6.x中方法签名的变化,并提供了三种解决方案:分次调用、自定义匹配器及降级使用`antMatchers()`。最后提醒开发者关注版本兼容性,确保升级平稳过渡。
128 2
|
2月前
|
存储 Java 文件存储
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— logback.xml 配置文件解析
本文解析了 `logback.xml` 配置文件的详细内容,包括日志输出格式、存储路径、控制台输出及日志级别等关键配置。通过定义 `LOG_PATTERN` 和 `FILE_PATH`,设置日志格式与存储路径;利用 `&lt;appender&gt;` 节点配置控制台和文件输出,支持日志滚动策略(如文件大小限制和保存时长);最后通过 `&lt;logger&gt;` 和 `&lt;root&gt;` 定义日志级别与输出方式。此配置适用于精细化管理日志输出,满足不同场景需求。
213 1
|
1月前
|
安全 Java 数据库
Spring Security 实战指南:从入门到精通
本文详细介绍了Spring Security在Java Web项目中的应用,涵盖登录、权限控制与安全防护等功能。通过Filter Chain过滤器链实现请求拦截与认证授权,核心组件包括AuthenticationProvider和UserDetailsService,负责用户信息加载与密码验证。文章还解析了项目结构,如SecurityConfig配置类、User实体类及自定义登录逻辑,并探讨了Method-Level Security、CSRF防护、Remember-Me等进阶功能。最后总结了Spring Security的核心机制与常见配置,帮助开发者构建健壮的安全系统。
139 0
|
1月前
|
前端开发 安全 Java
Spring Boot 便利店销售系统项目分包设计解析
本文深入解析了基于Spring Boot的便利店销售系统分包设计,通过清晰的分层架构(表现层、业务逻辑层、数据访问层等)和模块化设计,提升了代码的可维护性、复用性和扩展性。具体分包结构包括`controller`、`service`、`repository`、`entity`、`dto`、`config`和`util`等模块,职责分明,便于团队协作与功能迭代。该设计为复杂企业级应用开发提供了实践参考。
77 0
|
5天前
|
安全 Java API
Spring Boot 功能模块全解析:构建现代Java应用的技术图谱
Spring Boot不是一个单一的工具,而是一个由众多功能模块组成的生态系统。这些模块可以根据应用需求灵活组合,构建从简单的REST API到复杂的微服务系统,再到现代的AI驱动应用。
112 7
|
1月前
|
Java 关系型数据库 MySQL
深入解析 @Transactional——Spring 事务管理的核心
本文深入解析了 Spring Boot 中 `@Transactional` 的工作机制、常见陷阱及最佳实践。作为事务管理的核心注解,`@Transactional` 确保数据库操作的原子性,避免数据不一致问题。文章通过示例讲解了其基本用法、默认回滚规则(仅未捕获的运行时异常触发回滚)、因 `try-catch` 或方法访问修饰符不当导致失效的情况,以及数据库引擎对事务的支持要求。最后总结了使用 `@Transactional` 的五大最佳实践,帮助开发者规避常见问题,提升项目稳定性与可靠性。
198 12
|
1月前
|
缓存 安全 Java
深入解析HTTP请求方法:Spring Boot实战与最佳实践
这篇博客结合了HTTP规范、Spring Boot实现和实际工程经验,通过代码示例、对比表格和架构图等方式,系统性地讲解了不同HTTP方法的应用场景和最佳实践。
150 5
|
1月前
|
安全 Java 数据安全/隐私保护
Spring Security: 深入解析 AuthenticationSuccessHandler
本文深入解析了 Spring Security 中的 `AuthenticationSuccessHandler` 接口,它用于处理用户认证成功后的逻辑。通过实现该接口,开发者可自定义页面跳转、日志记录等功能。文章详细讲解了接口方法参数及使用场景,并提供了一个根据用户角色动态跳转页面的示例。结合 Spring Security 配置,展示了如何注册自定义的成功处理器,帮助开发者灵活应对认证后的多样化需求。
66 2
|
2月前
|
Java Spring
Spring Boot的核心注解是哪个?他由哪几个注解组成的?
Spring Boot的核心注解是@SpringBootApplication , 他由几个注解组成 : ● @SpringBootConfiguration: 组合了- @Configuration注解,实现配置文件的功能; ● @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项 ● @ComponentScan:Spring组件扫描

推荐镜像

更多