第一章 spring框架构成
第二章 spring容器
第三章 spring配置bean


文章目录

  • spring配置bean
    • 使用xml配置
      • 使用构造器创建
        • 依赖注入方式
          • setter方法注入
          • 构造方法注入
        • 配置bean引用
        • 配置集合属性
      • 使用工厂bean来创建实际bean
      • 使用静态工厂方法创建Bean
      • 调用实例工厂方法创建bean
      • 自动装配
        • 歧义性处理
    • 使用注解配置
      • 使用注解进行配置
        • 设置过滤
        • 设置包含
      • 自动装配
        • 歧义性处理

原文链接 https://zhhll.icu/2021/框架/spring/基础/3.spring配置bean/

spring配置bean

使用xml配置

使用构造器创建

构造器创建bean是最常用的,如果不使用构造注入,Spring会调用无参构造器来创建实例

使用的是反射机制,要求该bean所对应的类必须有一个无参构造器

而对于注入方式,有构造器注入和setter方法注入

依赖注入方式
setter方法注入

使用setter方法注入时,注意一定要有无参构造器,spring会根据配置的class来使用class.newInstance()方法来实例化该bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 配置beanclass 配置bean的全类名,使用反射的方式创建bean,要求必须有一个无参构造器id 标识容器z中的bean id唯一--><bean id="helloWorld" class="com.zhanghe.study.spring4.beans.helloworld.HelloWorld"><property name="name" value="Spring Hello"/></bean>
</beans>

注意:bean配置的property属性的name值表示的是setter风格的属性,即setter方法去掉set之后首字母小写的名称,并不是和成员变量进行对应

null值设置

<bean id="helloWorld" class="com.zhanghe.study.spring4.beans.helloworld.HelloWorld"><property name="name"><null/></property></bean>

注入不同的类型

  • 简单类型使用value

    <property name="name" value="Spring Hello"/>
    
  • 引用类型使用ref

    <property name="car" ref="car2"/>
    
  • 集合类型list

    <property name="cars"><list><ref bean="car"/><ref bean="car2"/></list>
    </property>
    
  • 集合类型set

    <property name="cars"><set><ref bean="car"/><ref bean="car2"/></set>
    </property>
    
  • 集合类型map

    <property name="carMap"><map><entry key="AA" value-ref="car"/><entry key="BB" value-ref="car2"/></map>
    </property>
    
  • 集合类型 properties

    <property name="testProp"><props><prop key="username">root</prop><prop key="password">123456</prop></props>
    </property>
    
构造方法注入
<!--
constructor-arg value为属性值index 表示对应构造器的参数位置  从0开始type 表示构造器该参数的类型ref  如果入参是bean
-->
<bean id="car" class="com.zhanghe.study.spring4.beans.beantest.Car"><constructor-arg value="法拉利" index="0"/><constructor-arg value="20000.0" type="double"/>
</bean>

获取bean

// 创建spring的IOC容器
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 从IOC容器获取HelloWorld  bean实例
HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");
配置bean引用

如果bean之间有引用关系,可以使用ref来指定引用关系

public class Person {private String name;private Car car;public String getName() {return name;}public void setName(String name) {this.name = name;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", car=" + car +'}';}
}

这里的ref中写的是其他bean的id值

<bean id="car" class="com.zhanghe.study.spring4.beans.beantest.Car"><constructor-arg value="法拉利" index="0"/><constructor-arg value="20000.0" type="double"/>
</bean><bean id="person" class="com.zhanghe.study.spring4.beans.beantest.Person"><property name="name" value="张三"/><property name="car" ref="car"/>
</bean>
配置集合属性

可以使用、、来对集合属性赋值

<bean id="person" class="com.zhanghe.study.spring4.beans.beantest.Person"><property name="name" value="张三"/><property name="car" ref="car"/><property name="cars"><!-- list的示例 --><list><ref bean="car"/><ref bean="car2"/></list></property><property name="carMap"><!-- map的示例  entry可以使用key/key-ref/value/value-ref --><map><entry key="AA" value-ref="car"/><entry key="BB" value-ref="car2"/></map></property>
</bean>

还有一种集合bean的方式,可以进行配置集合属性

<!-- 配置集合bean -->
<util:list id="cars"><ref bean="car"/><ref bean="car2"/>
</util:list>

然后在需要使用集合的bean中直接引用该集合bean

<bean id="person1" class="com.zhanghe.study.spring4.beans.beantest.Person"><property name="name" value="张三"/><property name="car" ref="car"/><!-- 引用上述定义的集合bean --><property name="cars" ref="cars"/>
</bean>

使用工厂bean来创建实际bean

对于某些对象的实例化过程特别的繁琐,更希望使用java代码来完成实例化过程,可以提供一个实现FactoryBean接口的工厂bean来生产所实际需要的bean对象

请区分开FactoryBean和BeanFactory,FactoryBean本身来说是一个bean,而BeanFactory确是Bean的工厂

/*** 实现FactoryBean接口来生成car对象* @author zh* @date 2021/1/30 16:01*/
public class CarFactoryBean implements FactoryBean<Car> {/*** 真正获取对象的方法* @return* @throws Exception*/@Overridepublic Car getObject() throws Exception {return new Car("玛莎拉蒂",300);}/*** 生成bean的类型* @return*/@Overridepublic Class<?> getObjectType() {return Car.class;}/*** 是否是单例* @return*/@Overridepublic boolean isSingleton() {return true;}
}

使用该factoryBean对象时,由于该bean实现了FactoryBean,所以spring不会把它作为一个普通的bean来处理,而是作为一个工厂bean,调用getObject()方法来创建实际需要的bean对象

<bean id="c" class="com.zhanghe.study.spring4.beans.beantest.CarFactoryBean"></bean>

使用静态工厂方法创建Bean

使用静态工厂方法创建bean实例时,class属性也必须指定,此时的class属性并不是指定Bean实例的实现类,而是静态工厂类,Spring通过该属性知道由哪个工厂类来创建Bean实例,还可以使用factory-method属性来指定静态工厂方法,Spring将调用静态工厂方法返回一个Bean实例,静态工厂方法需要参数的话,使用元素指定

public class StaticCarFactory {private static Map<String,Car> cars = new HashMap<>();static {cars.put("aa",new Car("aa",300));}public static Car getCar(String name){return cars.get(name);}
}
<!-- 通过静态工厂方法来配置bean
class 静态工厂类
factory-method 静态工厂方法的名字
constructor-arg 指定静态方法的参数
-->
<bean id="car" class="com.zhanghe.study.spring4.beans.beantest.StaticCarFactory"factory-method="getCar"><constructor-arg name="name" value="aa" index="0"/>
</bean>

优点:将对象创建的过程封装到静态方法中,当客户端需要对象时,只需要简单地调用静态方法,不需要关系创建对象的细节

调用实例工厂方法创建bean

实例工厂与静态工厂只有一个不同,静态工厂只需要使用工厂类即可,实例工厂需要工厂实例,使用factory-bean指定工厂实例

public class InstanceCarFactory {private Map<String,Car> cars = null;public InstanceCarFactory(){cars = new HashMap<>();cars.put("bb",new Car("bb", 30000.0));}public Car getCar(String name){return cars.get(name);}
}
<!-- 配置工厂实例 -->
<bean id="instanceCarFactory"     class="com.zhanghe.study.spring4.beans.beantest.InstanceCarFactory"/><!-- 通过实例工厂方法来配置beanfactory-bean 实例工厂的beanfactory-method 实例工厂方法的名字constructor-arg 指定方法的参数
-->
<bean id="car1" factory-bean="instanceCarFactory" factory-method="getCar"><constructor-arg name="name" value="bb" index="0"/>
</bean>

自动装配

上述的操作方式全是手动地进行注入的,如何进行自动装配呢,可以使用autowire属性来配置

<!-- 自动装配 -->
<!-- byName 根据属性名称去匹配到对应的beanbyName  根据属性的类型去匹配到对应的bean
-->
<bean id="testAutoWired" class="com.zhanghe.study.spring4.beans.beantest.Person" autowire="byName"><property name="name" value="张三"/>
</bean>

如果使用byType,而且存在多个该类型的bean的话,就会出现异常

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘com.zhanghe.study.spring4.beans.beantest.Car’ available: expected single matching bean but found 2: car,car2

歧义性处理

在自动装配时有时会遇到该接口有多个不同的实现类,此时spring不知道选择哪个来进行注入,就会出现NoUniqueBeanDefinitionException异常

可以使用primary来设置其中一个可选bean为首选项

<bean id="car" class="com.zhanghe.study.spring4.beans.beantest.Car" primary="true">

使用注解配置

spring可以在classpath下进行组件扫描,包含注解有

  • @Component 基本注解,表示是一个受spring管理的组件
  • @Respository 表示持久层组件
  • @Service 表示业务层组件
  • @Controller 表示表现层组件

spring扫描到组件后,有默认的命名策略,将扫描到的类名进行首字母小写,也可以在注解中使用value属性值来标识组件的名称

如果使用注解来标识bean的话,需要进行配置指定spring扫描的包,会扫描base-package指定的包及其子包

<context:component=scan base-package=“包名”/>

使用注解进行配置

使用注解进行配置时要先开启组件扫描

<!-- 开启组件扫描 设置包扫描路径,如果扫描多个包,使用,隔开 -->
<context:component-scan base-package="com.zhanghe.study.spring4.beans.annotationtest">
</context:component-scan>

还可以自定义的设置对于该包下的某些组件是否进行扫描

在使用<context:component=scan base-package=“包名”/>标签时,记得要加上context的命名空间

设置过滤

使用context:exclude-filter来设置排除哪些特定的组件

<context:component-scan base-package="com.zhanghe.study.spring4.beans.annotationtest"><!-- 使用context:exclude-filter来设置排除哪些特定的组件type  annotation表示使用注解的表达式assignable保护指定具体bean的类名--><context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/></context:component-scan>
设置包含

使用context:include-filter来设置只扫描哪些特定的组件

<context:component-scan base-package="com.zhanghe.study.spring4.beans.annotationtest" use-default-filters="false"><!-- 使用context:include-filter来设置只扫描哪些特定的组件,如果使用include-filter的话需要设置use-default-filters="false" --><context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>

自动装配

使用xml进行自动装配的时候略显笨拙,而且使用起来也并不顺心,因为autowire只能选择byName或者byType,如果存在多个相同类型的bean使用byType就会出现问题,大家可能因此想要放弃自动装配,其实自动装配与注解搭配起来还是很好用的,下面来了解一下

如果bean与bean之间存在关联关系,如在beanA中需要调用beanB的方法,如何来获取beanB中的实例呢?

<context:component-scan>元素会自动注册AutowiredAnnotationBeanPostProcessor实例和CommonAnnotationBeanPostProcessor实例,AutowiredAnnotationBeanPostProcessor实例可以自动装配具有@AutoWired注解的属性,CommonAnnotationBeanPostProcessor实例可以自动装配@Resource注解的属性

在基于注解方式实现属性注入时主要使用的四个注解

  • @Autowired默认使用byType,如果存在类型相同的两个bean,则使用byName来根据属性的名称来匹配bean,默认情况下该依赖对象必须存在,如果允许不存在,需要配置@Autowired(required = false)

  • @Qualifier 根据属性名称进行注入byName,需要和@Autowired一起使用,使其按照类型的基础上按照name进行注入,给字段注入时不可独立使用,必须要和@Autowired一起使用;但是给方法参数注入时,可以独立使用

  • @Resource注解可以根据类型注入,也可以根据名称注入,若使用的byName,需要提供bean的名称,如果不提供该bean的名称,则自动使用属性的名称进行匹配

  • @Inject与@AutoWired一样,只是没有required属性

    使用方式

  • 使用@Autowired 和@Qualifier结合来明确指定需要装配的Bean

    @Autowired
    @Qualifier("bpmServiceImpl")
    private BpmService bpmService;
    
  • 使用@Inject和@Named结合来指定

    @Inject
    @Named("compensateServiceImpl")
    private CompensateService compensateService;
    
歧义性处理

在自动装配时有时会遇到该接口有多个不同的实现类,此时spring不知道选择哪个来进行注入,就会出现NoUniqueBeanDefinitionException异常,可以使用@Primary来标注其中一个可选bean为首选项,也可以使用@Qualifier注解来选择注入哪个bean的id

spring配置bean相关推荐

  1. Spring配置Bean的方式

    配置Bean 基于XML配置Bean 基于注解配置Bean 基于Java类配置Bean 基于XML配置 ApplicationContext.xml <bean id="loginUs ...

  2. Spring配置Bean的几种方式

    ​ Spring容器提供了三种装配bean的方式,所谓装配就是指将bean配置在spring容器中,并能够在类与类之间提供依赖关系. 一.隐式Bean发现机制和自动装配 ​ Spring从两个角度来实 ...

  3. spring spring c3p0 mysql配置_Spring通过c3p0配置bean连接数据库

    Spring配置bean连接数据库两种方法: (1)直接在.xml文件内部配置: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&q ...

  4. Spring 配置JNDI(连接池)

    1. 找到Tomcat6.0安装目录下conf文件夹里的context.xml文件, 然后打开context.xml,在标签<context></<context>之间加 ...

  5. Spring 通过工厂方法(Factory Method)来配置bean

    在spring的世界中, 我们通常会利用bean config file 或者 annotation注解方式来配置bean. 在第一种利用bean config file(spring xml)方式中 ...

  6. Spring 学习笔记 3. 尚硅谷_佟刚_Spring_配置 Bean

    1,bean 的配置 <bean id="helloWorld" class="com.yfy.HelloWorld"><property n ...

  7. Spring之Bean的配置(二)

    目录 一.Bean的配置 1.自动装配 (1)简介 (2)缺点 2.继承Bean 3.依赖Bean配置 4.Bean的作用域 5.使用外部属性文件 6.注册PropertyPlaceholderCon ...

  8. Spring之Bean的配置(一)

    目录 一.概述 1.什么是Spring 2.作用 二.Spring中的Bean配置 1.IOC容器里配置bean 2.Spring容器 3.ApplicationContext 4.从IOC容器中获取 ...

  9. Spring 利用FactoryBean来配置Bean

    Spring 利用FactoryBean来配置Bean 在之前的 博文 已经介绍可以利用java反射机制 和 工厂方法(Factory Method)的方法来在bean config file里 配置 ...

最新文章

  1. Codeforces Round #649 (Div. 2)C. Ehab and Prefix MEXs[排列的构造]
  2. Kubernetes:通过自动化节省IT预算的4种方法
  3. [剑指offer]面试题第[7]题[JAVA][斐波那契数列][递归]
  4. web虚拟服务器4核32g,Web服务器配备四核的优势
  5. 分布式定时任务框架选型,写得太好了!
  6. Dangling meta character '?' near index 0
  7. Google正在失去DeepMind?
  8. mysql报错22_运行 mysql 遇到的两个报错
  9. 这个冬天,我以《监控》下酒
  10. Vue表格table样式
  11. cad批量逐个填充lisp,效率提高之CAD如何自动批量导出文本
  12. python十人抽奖小程序_利用python编写年会抽奖小程序
  13. Python英文搜索引擎(模糊搜索)
  14. 因特尔显卡自定义分辨率_如何在新版英特尔核芯显卡控制面板中自定义显示器分辨率...
  15. 华三V5交换机ssh配置
  16. 山东大学操作系统实验
  17. 重装系统笔记本电脑黑屏怎么办
  18. 433 490 868 915Mhz lora频段贴片天线方案 CA-S01 CrossAir贴片天线
  19. OpenGL三维变换与三维投影实例(行星绕日旋转)
  20. 推荐歌曲 一百首最经典的歌曲下载

热门文章

  1. Matlab绘制多组柱状图的方法(可直接复制)
  2. 密码学——现代密码体制总结(别再管哈希叫加密了噢~)
  3. E盘里多了个ppsds.pgf文件是怎么回事?
  4. 手机dpi修改工具_【原创教程】修改分辨率和dpi 让安卓手机不再卡顿
  5. 激光对射之智能变频技术
  6. 【go语言 socket编程系列】IPAddr类型及ResolveIPAddr方法
  7. PTA L1-020 帅到没朋友 (20 分)(C++)
  8. FL Studio水果最新版2023安装图文详细教程
  9. 360度全景的地拍如何制作?
  10. 高斯混合模型(Gaussian Mixture Model,GMM)