《Spring攻略(第2版)》——1.14 从Classpath中扫描组件

《Spring攻略(第2版)》——1.14 从Classpath中扫描组件

大家好,又见面了,我是全栈君。

本节书摘来自异步社区《Spring攻略(第2版)》一书中的第1章,第1.14节,作者: 【美】Gary Mak , Josh Long , Daniel Rubio著,更多章节内容可以访问云栖社区“异步社区”公众号查看

1.14 从Classpath中扫描组件

1.14.1 问题
为了便于Spring IoC容器对组件的管理,你需要在Bean配置中逐个声明它们。但是,如果Spring能够自动地监测你的组件而不需要手工配置,将会大大地节省你的工作量。

1.14.2 解决方案
Spring提供一个强大的功能——组件扫描。这个功能能够利用特殊的典型化注解,从classpath中自动地扫描、检测和实例化你的组件。指示Spring管理组件的基本注解是@Component。其他特殊的典型化注解包括@Repository、@Service和 @Controller。它们分别指示持续层、服务层和表现层中的组件。

1.14.3 工作原理
假定你被要求使用数据库序列开发序列生成器应用,将每个序列的前缀和后缀存储在一个表中。首先,你创建一个域类Sequence,包含id、Prefix和suffix属性。

package com.apress.springrecipes.sequence;

public class Sequence {

   private String id;
   private String prefix;
   private String suffix;

   // Constructors, Getters, and Setters
   ...
}

然后,你为数据访问对象(DAO)创建一个接口,负责从数据库访问数据。getSequence()方法从表中按照ID装入Sequence对象,而getNextValue()方法读取特定数据库序列的下一个值。

package com.apress.springrecipes.sequence;

public interface SequenceDao {

   public Sequence getSequence(String sequenceId);
   public int getNextValue(String sequenceId);
}

在生产应用中,你应该使用某种数据访问技术如JDBC或者对象/关系映射实现这个DAO接口。但是为了测试的目的,我们使用Map来存储序列实例和值。

package com.apress.springrecipes.sequence;
...
public class SequenceDaoImpl implements SequenceDao {

   private Map<String, Sequence> sequences;
   private Map<String, Integer> values;

   public SequenceDaoImpl() {
     sequences = new HashMap<String, Sequence>();
     sequences.put("IT", new Sequence("IT", "30", "A"));
     values = new HashMap<String, Integer>();
     values.put("IT", 100000);
}

   public Sequence getSequence(String sequenceId) {
     return sequences.get(sequenceId);
   }

   public synchronized int getNextValue(String sequenceId) {
     int value = values.get(sequenceId);
     values.put(sequenceId, value + 1);
     return value;
   }
}

你还需要一个服务对象作为外观(Façade),提供序列生成服务。在内部,这个服务对象将与DAO交互,处理序列生成请求。所以它要求对DAO的引用。

package com.apress.springrecipes.sequence;

public class SequenceService {

   private SequenceDao sequenceDao;

   public void setSequenceDao(SequenceDao sequenceDao) {
     this.sequenceDao = sequenceDao;
   }

   public String generate(String sequenceId) {
     Sequence sequence = sequenceDao.getSequence(sequenceId);
     int value = sequenceDao.getNextValue(sequenceId);
     return sequence.getPrefix() + value + sequence.getSuffix();
   }
}

最后,你必须在Bean配置文件中配置这些组件,使序列生成器应用正常工作。你可以自动装配组件以减少配置量。

<beans ...>
   <bean id="sequenceService"
     class="com.apress.springrecipes.sequence.SequenceService"
     autowire="byType" />

   <bean id="sequenceDao"
     class="com.apress.springrecipes.sequence.SequenceDaoImpl" />
</beans>

然后,你可以用下列的Main类测试前述的组件:

package com.apress.springrecipes.sequence;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

   public static void main(String[] args) {
     ApplicationContext context =
        new ClassPathXmlApplicationContext("beans.xml");

     SequenceService sequenceService =
        (SequenceService) context.getBean("sequenceService");

     System.out.println(sequenceService.generate("IT"));
     System.out.println(sequenceService.generate("IT"));
   }
}

自动扫描组件
从Spring 2.5版本开始提供的组件扫描功能能够自动地从Classpath中扫描、检测和实例化你的组件。默认情况下,Spring可以检测所有带有典型化注解的组件。指示Spring管理组件的基本注解是@Component。你可以将其应用到SequenceDaoImpl类。

package com.apress.springrecipes.sequence;

import org.springframework.stereotype.Component;
import java.util.Map;

@Component
public class SequenceDaoImpl implements SequenceDao {
   ...
}

你也可以将这种典型化注解应用到SequenceService类,让Spring检测它。此外,应用@Autowired注解到DAO字段,让Spring按照类型进行自动装配。注意,因为你在一个字段上使用注解,所以不需要设值方法。

package com.apress.springrecipes.sequence;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class SequenceService {

   @Autowired
   private SequenceDao sequenceDao;
   ...
}

有了应用到组件类的典型化注解,就能通过声明一个XML元素,要求Spring扫描这些注解。在这个元素中,你必须指定扫描组件所用的包。然后指定的包和子包都将被扫描。你可以使用分号来分隔多个扫描包。

前面的模式足以使用Bean。Spring将把类名第一个字符小写,对其余部分采用Camel- cased命名法1组成Bean名称。因此,下面的语句是有效的(假定你已经实例化了一个包含元素的应用上下文)。

SequenceService sequenceService = (SequenceService) context.getBean("sequenceService");

注意,这个元素还将注册一个AutowiredAnnotationBeanPostProcessor实例,这个实例能够自动装配带有@Autowired注解的属性。

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd">

   <context:component-scan base-package="com.apress.springrecipes.sequence" />
</beans>

@Component注解是指示一般用途的组件的基本典型化注解。实际上,还有其他具体的典型化注解,指示不同层次中的组件。首先,@Repository典型化注解指示持续层中的一个DAO组件。

package com.apress.springrecipes.sequence;

import org.springframework.stereotype.Repository;

@Repository
public class SequenceDaoImpl implements SequenceDao {
   ...
}

然后,@Service典型化注解指示服务层中的一个服务组件。

package com.apress.springrecipes.sequence;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class SequenceService {

   @Autowired
   private SequenceDao sequenceDao;
   ...
}

另一个组件典型化注解@Controller指示表现层中的一个控制器组件。在第8章“Spring @MVC”中还将介绍。

过滤扫描的组件
默认情况下,Spring将检测所有用@Component、@Repository、@Service、@Controller或者本身加上@Component注解的自定义注解类型。你可以应用一个或多个包含/排除过滤器自定义这一扫描。

Spring支持4种过滤器表达式。annotation和assignable类型用于指定过滤的注解类型和类/接口。regex和aspectj类型允许指定正则表达式和AspectJ切入点表达式匹配类。你还可以用use-default-filters属性禁用默认过滤器。

例如,下面的组件扫描包含了所有名称中包含Dao或Service的类,排除带有@Controller注解的类:

<beans ...>
   <context:component-scan base-package="com.apress.springrecipes.sequence">
     <context:include-filter type="regex"
        expression="com\.apress\.springrecipes\.sequence\..*Dao.*" />
     <context:include-filter type="regex"
        expression="com\.apress\.springrecipes\.sequence\..*Service.*" />
     <context:exclude-filter type="annotation"
        expression="org.springframework.stereotype.Controller" />
   </context:component-scan>
</beans>

因为你已经应用了include过滤器检测所有名称包含Dao或者Service的类,SequenceDaoImpl和SequenceService组件就能在没有典型化注解的情况下被自动检测出来。

命名检测到的组件
默认情况下,Spring将非限定类名的第一个字符改为小写来命名检测到的组件。例如,SequenceService类将被命名为sequenceService。你可以在典型化注解值中显式地指定组件的名称。

package com.apress.springrecipes.sequence;
...
import org.springframework.stereotype.Service;

@Service("sequenceService")
public class SequenceService {
   ...
}

package com.apress.springrecipes.sequence;

import org.springframework.stereotype.Repository;

@Repository("sequenceDao")
public class SequenceDaoImpl implements SequenceDao {
   ...
}

你可以实现BeanNameGenerator接口,并在元素的name-generator属性中指定自己的命名策略。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/108457.html原文链接:https://javaforall.net

(0)
上一篇 2022年3月3日 下午6:00
下一篇 2022年3月3日 下午7:00


相关推荐

  • 脚本计算机术语,谁能给我简单明了的解释一下脚本是什么意思?

    脚本计算机术语,谁能给我简单明了的解释一下脚本是什么意思?张雅熙 i 回答数 138 被采纳数 02 0618 28 12 计算机专业术语脚本 script 是一种宏或是大家通常说的脚本语言 即然是一种计算机语言也就说明了它可以进行程序的编制 而可以实现在计算机上运行 计算机语言分三个层次以硬件为最底层和硬件相关的代码叫机器码它是 16 进制的形式保存 而运行时状态是 2 进制的机器码人是无法直接看懂的 从源代码的角度来说和机器码最

    2025年10月1日
    8
  • 索引优缺点

    索引优缺点一、为什么要创建索引呢(优点)?创建索引可以大大提高系统的性能。第一,   通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。第二,   可以大大加快数据的检索速度,这也是创建索引的最主要的原因。第三,   可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。第四,   在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。第五,   通过使用索引,…

    2022年5月26日
    44
  • MySQL集群架构[通俗易懂]

    MySQL集群架构[通俗易懂]本文知识点较多,篇幅较长,请耐心学习题记:文章内容输出来源:拉勾教育Java高薪训练营。本篇文章是MySQL学习课程中的一部分笔记。MySQL集群架构一、集群架构设计1、架构设计理念在集群架构设计时,主要遵从下面三个维度:可用性扩展性一致性2、可用性设计站点高可用,冗余站点服务高可用,冗余服务数据高可用,冗余数据保证高可用的方法是冗余。但是数据冗余带来的问题是数据一致性问题。实现高可用的方案有以下几种架构模式:主从模式简单灵活,能满足多种需求。比较主流的.

    2022年7月27日
    6
  • IDEA配置注释模板

    IDEA配置注释模板IDEA 配置注释模板一 配置类注释模板 1 File setting Editor LiveTemplate 如下图所示 2 点击右侧 号 选择创建模板组 并输入模板的名称 具体如下图所示 3 选择刚刚新建的模板组 点击右侧 号 创建新模板 具体如下图所示 4 配置模板快捷键 配置模板内容 点击 Define 会出现列表 选择

    2026年3月19日
    3
  • jdbc连接mysql5.7_JDBC连接MySQL5.7的方法

    jdbc连接mysql5.7_JDBC连接MySQL5.7的方法1.首先准备mysql和eclipse环境,在环境搭建好之后,从eclipse官网下载jdbc的驱动包,下载地址http://dev.mysql.com/downloads/connector/j/2.从下载的文件中取出mysql-connector-java-5.1.31-bin.jar,放到工程中,并导入路径方法:右击工程名->BuildPath->ConfigureBuil…

    2025年10月10日
    4
  • 开源自动化智能体工具 OpenManus 安装教程

    开源自动化智能体工具 OpenManus 安装教程

    2026年3月15日
    1

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号