2.3 Bean装配

简介: <div style="background-color:inherit">1、Spring容器成功启动的条件</div> <div style="background-color:inherit"> <ul style="margin-top:0px; margin-bottom:0px; background-color:inherit"><li style="backgroun
1、Spring容器成功启动的条件
  • Spring框架的类包都已放在应用程序的类路径;
  • 应用程序为Spring提供完备的Bean信息;
  • Bean的类都已放到应用程序的类路径下。

2、Bean配置信息是Bean的元素据信息,由4个方面组成:
  • Bean的实现类;
  • Bean的属性信息(如数据源的连接数、用户名、密码);
  • bean的依赖关系,Spring根据依赖关系配置完成Bean间的装配;
  • Bean的行为配置(如生命周期范围及生命周期各过程的回调函数)。

2.3.1 Bean基本配置

Bean命名      
       id为Bean的名称,通过容器的getBean("foo")获取对应的Bean,在容器中起到定位查找的作用,是外部程序和Spring IoC容器进行交互的桥梁,class指定了Bean对应的实现类。
         id(XML规定的特殊属性)在IoC容器中必须 唯一,还需满足XML对id的命名规范:字母开始,后接字母、数字、连字符、下划线、句号、冒号等完整结束符。逗号、空格这些非完整结束符是非法的。
        name属性几乎可用任何字符,
<bean name="#car" class="com.Car"/>
        id和name都可指定多个名字,名字间用逗号、分号或空格分隔。用户可用getBean("123")或另外两种名字获取IoC容器中的CarBean。
<bean  name="#car,123,$Car"  class="com.Car"/>
         Spring配置文件不允许两个相同id的<bean>;但允许相同name的<bean>,getBean时会返回最后声明的那个Bean,后面的Bean覆盖了前面同名的Bean。So,尽量使用id而不是name命名的Bean。
        如果id、name都未指定,如① <bean   class="com.Car"/>,Spring自动将全限定类名作为Bean的名称,可通过②getBean("com.Car")获取CarBean,如果存在多个实现类相同的匿名<bean>即多个①处的Bean,第一个Bean通过②获得,第二个Bean通过getBean("com.Car#1")获得,以此类推。

2.3.2 依赖注入

1)属性注入
    setXxx()方法,可选择性、灵活性高,最常用。
    要求Bean提供默认的构造函数,并未需要注入的属性提供对应的Setter方法。Spring先调用Bean的默认    构造函数实例化Bean对象,然后通过反射调用Setter方法注入属性值。
【默认构造函数】
        默认构造函数不带参。Java规定如果类中没有定义任何构造函数,JVM自动生成一个默认构造函数。反之,如果类中显示定义了构造函数,JVM将不会自动生成。So,类中显示定义了一个带参构造函数,则需同时提供一个默认构造函数,否则属性注入时将抛出异常。
        Spring只会检查Bean中是否有对应的Setter,是否有对应属性变量则不作要求。但一般约定俗成在Bean中提供同名的属性变量。
【Java属性变量】
        一般以小写字母起头,JavaBean允许大写字母开头,但必须满足“变量的前两个字母要么全部大写,要么全部小写”,brand、IDCode合法,iC、IDCode非法。

2)构造函数注入
        保证一些必要属性在Bean实例化时就得到设置,并确保Bean实例在实例化后就可以使用。使用构造函数的前提是Bean必须提供带参的构造函数。
Spring中构造函数注入的配置方式

注入时若匹配的构造函数不止一个,默认匹配最后一个构造函数。

Bean存在多个构造函数时,尽可能显示指定index、type。

①ByType:
<!--构造注入-类型匹配入参-->

<bean id="car1" class="com.smart.injection.Car">
    <
constructor-arg type="java.lang.String">
        <
value>红旗CA72</value>
    </
constructor-arg>
    <
constructor-arg type="double">
        <
value>20000</value>
    </
constructor-arg>
    
<!--Car Bean中必须有和此处一致的构造函数(Stringdouble参数的构造函数)-->
</bean>


 ②ByIndex:

<!--构造注入-索引匹配入参-->
<bean id="carIndex" class="com.smart.injection.Car">
    
<!--索引从0开始-->
    
<constructor-arg index="0" value="红旗CA72"/>
    <
constructor-arg index="1" value="中国一汽"/>
    <
constructor-arg index="2" value="20000"/>
    
<!-- 必须有一个3个入参的构造函数,如果不止一个,将以最后一个构造函数为准 -->
</bean>


 ③ByTypeIndex:

<!--构造注入-类型、索引 联合匹配入参-->
<bean id="carTypeIndex" class="com.smart.injection.Car">
<constructor-arg index="0" type="java.lang.String">
<value>红旗CA72</value>
</constructor-arg>
<constructor-arg index="1" type="java.lang.String" value="中国一汽"/>
<!-- constructor-arg两种格式均可 -->
<!-- intdouble直接写,不加java.lang,否则异常Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities) -->
<constructor-arg index="2" type="double">
<value>20000</value>
</constructor-arg>
</bean>
 ④ByReflection:
<!-- 构造注入-自身类型反射reflection -->
<bean id="office" class="com.smart.injection.Office"/>
<bean id="boss" class="com.smart.injection.Boss">
<!--未设置typeindex,通过入参值的类型完后匹配映射-->
<constructor-arg><value>xiaofan</value></constructor-arg>
<!--ref引用现有bean-->
<constructor-arg><ref bean="car"/></constructor-arg>
<constructor-arg><ref bean="office"/></constructor-arg>
</bean>
3)循环依赖问题

        Spring容器顺利实例化以构造函数方式配置的Bean的前提是:Bean构造函数引用的对象已经就绪。
如果两个Bean均通过构造函数注入,且通过构造函数入参引用对方,就会发生类似线程死锁的循环依赖问题。

<bean id="boss" ……ref="car">
<bean id="car" ……ref="boss">
因为循环依赖问题,Spring容器无法启动,将构造函数注入方式调整为属性注入即可。
2.3.3 注入参数详解
  • ①字面值--可通过<value>元素标签注入
字面值一般指可用字符串表示的值,如基本数据类型及其封装类、String。Spring内部编辑器可将以字符串表示的字面值转化为内部变量的相应类型。
特殊处理标签:
<![CDATA[ str ]]>,作用是让XML解析器将标签中的字符串当做普通文本对待,防止某些字符串对XML格式造成破坏。
<value><![CDATA[红旗CA72]]></value>
  • 引用其他Bean--<ref>
<ref bean="car"/>
<ref>元素引用Bean的3个属性:
    bean:引用同一容器或父容器的Bean,最常见。
    local:只能引用同一配置文件的Bean,可利用XML解析器自动检验引用的合法性。
    parent:引用父容器的Bean。

  • ③集合类型属性
主要包括List、Set、Map、Properties。
<bean id="boss_list" class="com.smart.injection.Boss">
<!--List属性既可通过value注入字符串,也可ref引用其他bean-->
<property name="list">
<list>
<value>Java</value>
<value>Pathon</value>
</list>
</property>
</bean>
<bean id="boss_map" class="com.smart.injection.Boss">
<property name="mapWeek">
<map>
<entry>
<key><value>Mon</value></key>
<value>Reading</value>
</entry>
<entry>
<key><value>Tues</value></key>
<value>Sporting</value>
</entry>
<!-- 如果Map元素的键和值都是对象,可以ref
<entry>
<key><ref bean="keyBean"/></key>
<ref bean="valueBean"/>
</entry> -->
</map>
</property>
</bean>
<bean id="boss_pro" class="com.smart.injection.Boss">
<!--Properties键值只能是字符串,值的配置没有value标签-->
<property name="type">
<props>
<prop key="IDE">IDEA</prop>
<prop key="SQL">MySQL</prop>
</props>
</property>
</bean>
  • ④通过util命名空间配置集合类型的Bean
<!--需在Spring配置文件引入util命名空间-->
<util:list id="list_util" list-class="java.util.LinkedList">
<value>Coding</value>
<value>Walk</value>
<!--Set类似-->
</util:list>
<util:map id="map_util">
<entry key="Wed" value="Java"/>
<entry key="Thu" value="Spring"/>
</util:map>
<!-- <util:list>Set支持value-type属性;Map支持key-typevalue-type属性,指定键值类型 -->
  • ⑤简化配置方式
<!--简化XML配置:采用属性而非子元素配置信息-->
<!--Spring从2.5开始引入p命名空间,使用前需声明xmlns:p="http:~schema/p"-->

<bean id="car" class="com.smart.injection.Car"
p:brand="红旗CA72"
p:maxSpeed="260"/>
<bean id="boss" class="com.smart.injection.Boss"
p:car-ref="car"/>
 
   
  • ⑤自动装配 autowire=“<自动装配类型>”
Spring IoC容器了解容器中所有的Bean信息,通过Java反射机制获知实现类的结构信息,开发人员可按照规则进行Bean的字段装配。
Spring提供了4种自动装配类型。<beans>元素标签中的default-autowired属性可配置为全局自动匹配,默认为0,表示不启用自动装配。其他可选配置如下图,byName,byType,constructor,autodetect。

减轻配置工作量,但造成配置文件Bean间关系不清楚,易引发潜在错误,因此实际项目建议少用。

  
  
2.3.4 Bean作用域
Spring2.0前仅有2个作用域:singleton和prototype。2.0开始针对WebApplicationContext新添了3个作用域。

Spring低版本由于只有2个作用域,So采用singleton=“true|false”的配置方式,为向后兼容,现依旧可用。
Spring新配置方式:scope=“<作用域类型>”

<bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/>

除以上5种,Spring还允许用户自定义Bean的作用域。org.springframework.beans.factory.config.Scope接口定义新作用域,再通过org。springframework.beans.factory.config.CustomScopeConfigurer这个BeanFactoryPostProcessor注册自定义的Bean作用域。【很少需要用户自定义作用域,自带的足以满足大部分需求】

2.3.5 基于注解的配置

1)使用注解定义Bean
基于XML的配置,Bean定义信息和Bean实现类本身分离;
基于注解的配置,Bean定义信息通过在Bean实现类上标注注解实现。

@Component("userDao")

    public class UserDao{……}

等价于一下XML配置:
<bean id="userDao" class="com.smart.UserDao"/>
@Component外,Spring还提供3个功能基本和其等效的注解,也称为Bean的衍型注解。
@Repository:标注Dao实现类
@Service:标注Service实现类
@Controller:标注Web层的Controller实现类 衍型注解让注解本身用途清晰化,也被Spring赋予了一些特殊的功能。【推荐使用】

2)使用注解配置信息启动Spring容器
Spring2.5后提供了context命名空间,提供了提供扫描包以应用注解定义Bean的方式。
使用方式:
a、声明context命名空间, xmlns:context ="http://www.springframework.org/schema/context"
b、扫描类包以应用注解定义的Bean,<context:component-scanbase-package="com.smart.anno">
context的命名空间的component-scan的base-package属性指定一个需要扫描的基类包,Spring将扫描此基类包的所有类,并从注解信息中获取Bean信息。
c、resource-pattern:过滤出特定类,仅扫描特定类而非基类包下的所有类。
<context:component-scanbase-package="com.smart" resource-pattern="anno/*.class">
resource-pattern属性默认值为“**/*.class”,即基类包里的所有类。此处设置为"anno/*.class",Spring仅会扫描基类包anno子包中的类。
d、<context:component-scan>过滤子元素,如仅过滤基类包中实现了XXXService接口的类或标注了某个特定注解的类等,而resource-pattern仅可按资源名称过滤。
<context:component-scan base-package="com.smart">
<context:include-filter type="regex" expression="com\.smart\.anno.*"/>
<context:exclude-filter type="aspectj" expression="com.smart..*Controller+"/>
</context:component-scan>
<context:include-filter>表示要包含的类,<context:exclude-filter>表示要排除的类;一个component-scan下可包含若干个exclude和include。且这两个过滤元素均支持多种类型的过滤表达式。

过滤类型中,除custom外,aspectj过滤表达能力最强,可轻易实现其他类型所表达的过滤规则。

3)自动装配Bean【@Autowired】
@Service //定义一个Service,将UserService标注为一个Bean
public class UserService {
// 注入UserDao这个Dao层的Bean
@Autowired
private UserDao userDao ;
}
@Autowired:默认按类型匹配,当有且仅有一个匹配的Bean时,Spring将其注入@Autowired标注的变量中。
  • ①@Autowired的requried属性
若容器中没有和按标注类型匹配的Bean,Spring将抛出NoSuchBeanDefinitionException异常,如果希望即使找不到匹配的Bean也不要抛出异常,可使用@Autowired(required = false)进行标注。【required默认值为true】

  • @Qualifier指定注入Bean的名称
如果有超过一个匹配的Bean,可通过@Qualifier注解限定Bean的名称。
@Autowired
@Qualifier("userDao") //
private UserDao userDao;
假设容器有两个类型UserDao的Bean,一个名为UserDao, 一个名为UserDao2,则①处会注入名为UserDao的Bean。

  • ③标注类方法
@Autowired 可标注类成员变量及方法的入参,亦可标注类。
@Autowired //自动将LogDao传给方法入参
public void setLogDao(LogDao logDao) {
    this.logDao = logDao;
}

@Autowired // 自动将,名为UserDao的Bean传给方法入参
@Qualifier("userDao")
public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
}
如果一个方法拥有多个入参,默认情况下,Spring自动选择匹配入参类型的Bean进行注入,Spring允许使用@Qualifier指定 注入 入参的 Bean的名称。
@Autowired
public void init( @Qualifier("userDao")UserDao userDao,LogDao logDao){
     this.userDao = userDao;
     this.logDao =logDao;
}
以上例子,UserDao的入参注入名为UserDao的Bean,而LogDao的入参注入LogDao类型的Bean。
Note:
通常,Spring容器的大部分Bean是单实例,So无需通过@Repository、@Service等注解的value属性指定名称,也无需使用@Qualifier按名称注入。

  • ④标注集合类
Spring将容器中所有类型为Plugin的Bean注入这个变量中。
@Component
public class MyComponent {
@Autowired(required = false)
private List<Plugin> plugins;

public List<Plugin> getPlugins() {
return plugins;
}
}
此处,Plugin为接口,有两个实现类且两个实现类都通过@Component标注为Bean,So Spring会将这两个Bean都注入plugins。

2.3.6 基于Java类的配置

1)使用Java类提供Bean定义信息

@Configuration // 此注解说明此类可用于为Spring提供Bean的定义信息
public class AppConf {
    @Bean // 将一个POJO标注为定义Bean的配置类
    public UserDao userDao() {
        return new UserDao();
    }
    @Bean // Bean类型由方法返回值类型决定,名称默认和方法名相同,亦可显示指定。
    public LogDao logDao() {
        return new LogDao();
    }
    @Bean (name="LogonService")
    public LogonService logonService() {
        LogonService logonService = new LogonService();
        logonService.setLogDao(logDao()); // 注入上面定义的Bean
        logonService.setUserDao(userDao());
        return logonService;
    }
}
以上配置等价于
<bean id="userDao" class="com.smart.anno.UserDao"/>
<bean id="logDao" class="com.smart.anno.LogDao"/>
<bean id="logonService" class="com.smart.conf.LogonService"
     p:logDao-ref="userDao" p:userDao-ref="logDao"/>
对比:
基于Java类的配置方式:更灵活地实现Bean的实例化及Bean之间的装配;
XML或基于注解: 通过配置声明,灵活性略逊,但配置更简单。
@Configuration
public class  DaoConfig {
    @Bean
    public UserDao userDao(){
        return new UserDao();
    }
     @Scope("prototype")
    @Bean
    public LogDao logDao(){
        return new LogDao();
    }
}
------------------------
@Configuration
public class  ServiceConfig {
    @Autowired
    private DaoConfig daoConfig;
    @Bean
    public LogonService logonService() {
        LogonService logonService = new LogonService();
        System.out.println(daoConfig.logDao() == daoConfig.logDao());
        logonService.setLogDao(daoConfig.logDao()); //A、像普通Bean一样调用其他Bean方法
        logonService.setUserDao(daoConfig.userDao());
        return logonService;
    }
}
  • @Configuration注解类本身相当于标注了@Component,即可像普通Bean一样被注入其他Bean中(可直接调用@Configuration中标注@Bean的方法,如上)。
  • Spring对配置类所有标注@Bean的方法进行AOP增强,将对声明周期的逻辑植入进来。
  • A处调用daoConfig.logDao()逻辑:从Spring容器返回相应Bean的单例,即多次调用daoConfig.logDao()返回的都是相同Bean。Bean若标注@Scope("prototype"),则每次返回新的Bean。

2)直接通过@Configuration类启动Spring容器
// 使用@Configuration类中提供的Bean定义信息启动Spring容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConf.class); //直接传入 @Configuration标注的Java类
LogonService logonService = ctx.getBean(LogonService.class);
注:
AnnotationConfigApplicationContext支持加载多个配置类
 
//2.通过编码方式注册配置类
AnnotationConfigApplicationContext ctx2 = new AnnotationConfigApplicationContext();
ctx2.register(DaoConfig.class);
ctx2.register(ServiceConfig.class);
ctx2.refresh(); //刷新容器以应用这些注册的配置类

 //3.@Import将多个配置类组装到一个配置类中,仅需注册这个组装好的配置类即可启动容器。
@Configuration
@Import(DaoConfig.class)
public class ServiceConfig {

    @Autowired
    private DaoConfig daoConfig;

    @Bean
    public LogonService logonService() {
        LogonService logonService = new LogonService();
        return logonService;
    }
}

3)XML配置文件引用@Configuration的配置
// 通过上下文扫描加载到AppConf的配置类
<context:component-scan base-package="com.smart.conf"
        resource-pattern="AppConf.class" />

4)通过Configuration配置类引用XML配置信息
beans3.xml:
<bean id="userDao" class="com.smart.conf.UserDao"/>
-----------------
@Configuration
@ImportResource("classpath:com/smart/conf/beans3.xml") //自动注入XML文件中定义的Bean
public class LogonAppConfig {
@Bean // 定义一个LogonService的Bean
@Autowired // 通过入参自动注入UserDao和LogDao的Bean
public LogonService logonService(UserDao userDao, LogDao logDao) {
LogonService logonService = new LogonService();
logonService.setUserDao(userDao);
logonService.setLogDao(logDao);
return logonService;
}
}

2.3.7 基于XML、注解、Java类三种配置方式的比较


通常基于Java类的方式使用较少。



目录
相关文章
|
15天前
|
人工智能 自然语言处理 Shell
🦞 如何在 OpenClaw (Clawdbot/Moltbot) 配置阿里云百炼 API
本教程指导用户在开源AI助手Clawdbot中集成阿里云百炼API,涵盖安装Clawdbot、获取百炼API Key、配置环境变量与模型参数、验证调用等完整流程,支持Qwen3-max thinking (Qwen3-Max-2026-01-23)/Qwen - Plus等主流模型,助力本地化智能自动化。
28994 101
🦞 如何在 OpenClaw (Clawdbot/Moltbot) 配置阿里云百炼 API
|
4天前
|
应用服务中间件 API 网络安全
3分钟汉化OpenClaw,使用Docker快速部署启动OpenClaw(Clawdbot)教程
2026年全新推出的OpenClaw汉化版,是基于Claude API开发的智能对话系统本土化优化版本,解决了原版英文界面的使用壁垒,实现了界面、文档、指令的全中文适配。该版本采用Docker容器化部署方案,开箱即用,支持Linux、macOS、Windows全平台运行,适配个人、企业、生产等多种使用场景,同时具备灵活的配置选项和强大的扩展能力。本文将从项目简介、部署前准备、快速部署、详细配置、问题排查、监控维护等方面,提供完整的部署与使用指南,文中包含实操代码命令,确保不同技术水平的用户都能快速落地使用。
3545 0
|
10天前
|
人工智能 安全 机器人
OpenClaw(原 Clawdbot)钉钉对接保姆级教程 手把手教你打造自己的 AI 助手
OpenClaw(原Clawdbot)是一款开源本地AI助手,支持钉钉、飞书等多平台接入。本教程手把手指导Linux下部署与钉钉机器人对接,涵盖环境配置、模型选择(如Qwen)、权限设置及调试,助你快速打造私有、安全、高权限的专属AI助理。(239字)
5709 16
OpenClaw(原 Clawdbot)钉钉对接保姆级教程 手把手教你打造自己的 AI 助手
|
9天前
|
人工智能 机器人 Linux
OpenClaw(Clawdbot、Moltbot)汉化版部署教程指南(零门槛)
OpenClaw作为2026年GitHub上增长最快的开源项目之一,一周内Stars从7800飙升至12万+,其核心优势在于打破传统聊天机器人的局限,能真正执行读写文件、运行脚本、浏览器自动化等实操任务。但原版全英文界面对中文用户存在上手门槛,汉化版通过覆盖命令行(CLI)与网页控制台(Dashboard)核心模块,解决了语言障碍,同时保持与官方版本的实时同步,确保新功能最快1小时内可用。本文将详细拆解汉化版OpenClaw的搭建流程,涵盖本地安装、Docker部署、服务器远程访问等场景,同时提供环境适配、问题排查与国内应用集成方案,助力中文用户高效搭建专属AI助手。
4116 8
|
11天前
|
人工智能 机器人 Linux
保姆级 OpenClaw (原 Clawdbot)飞书对接教程 手把手教你搭建 AI 助手
OpenClaw(原Clawdbot)是一款开源本地AI智能体,支持飞书等多平台对接。本教程手把手教你Linux下部署,实现数据私有、系统控制、网页浏览与代码编写,全程保姆级操作,240字内搞定专属AI助手搭建!
5210 17
保姆级 OpenClaw (原 Clawdbot)飞书对接教程 手把手教你搭建 AI 助手
|
11天前
|
存储 人工智能 机器人
OpenClaw是什么?阿里云OpenClaw(原Clawdbot/Moltbot)一键部署官方教程参考
OpenClaw是什么?OpenClaw(原Clawdbot/Moltbot)是一款实用的个人AI助理,能够24小时响应指令并执行任务,如处理文件、查询信息、自动化协同等。阿里云推出的OpenClaw一键部署方案,简化了复杂配置流程,用户无需专业技术储备,即可快速在轻量应用服务器上启用该服务,打造专属AI助理。本文将详细拆解部署全流程、进阶功能配置及常见问题解决方案,确保不改变原意且无营销表述。
5664 5
|
13天前
|
人工智能 JavaScript 应用服务中间件
零门槛部署本地AI助手:Windows系统Moltbot(Clawdbot)保姆级教程
Moltbot(原Clawdbot)是一款功能全面的智能体AI助手,不仅能通过聊天互动响应需求,还具备“动手”和“跑腿”能力——“手”可读写本地文件、执行代码、操控命令行,“脚”能联网搜索、访问网页并分析内容,“大脑”则可接入Qwen、OpenAI等云端API,或利用本地GPU运行模型。本教程专为Windows系统用户打造,从环境搭建到问题排查,详细拆解全流程,即使无技术基础也能顺利部署本地AI助理。
7511 16
|
13天前
|
人工智能 JavaScript API
零门槛部署本地 AI 助手:Clawdbot/Meltbot 部署深度保姆级教程
Clawdbot(Moltbot)是一款智能体AI助手,具备“手”(读写文件、执行代码)、“脚”(联网搜索、分析网页)和“脑”(接入Qwen/OpenAI等API或本地GPU模型)。本指南详解Windows下从Node.js环境搭建、一键安装到Token配置的全流程,助你快速部署本地AI助理。(239字)
5132 22