spring在IoC容器中装配Bean详解

1、Spring配置概述

1.1、概述

Spring容器从xml配置、java注解、spring注解中读取bean配置信息,形成bean定义注册表;

根据bean定义注册表实例化bean;

将bean实例放入bean缓存池;

应用程序使用bean。

1.2、基于xml的配置

(1)xml文件概述

xmlns------默认命名空间

xmlns:xsi-------标准命名空间,用于指定自定义命名空间的schema文件

xmlns:xxx=“aaaaa”-------自定义命名空间,xxx是别名,后面的值aaaa是全名

xsi:schemaLocation----------为每个命名空间指定具体的schema文件,格式:命名空间全名文件地址。。。用空格隔开

2、Bean基本配置

2.1、Bean的命名

(1)id和name都可以指定多个名字,名字之间用逗号,分号或空格进行分隔

<beanname="#car,123,$car"class="xxxxxxxxx">

用户可以使用getBean("#car"),getBean("123"),getBean("$car")获取bean。

(2)如果没有指定id和name属性,则spring自动将类的全限定名作为bean的名称

(3)如果存在多个匿名bean,即没有指定id和name的<bean/>,假设类的全限定名为xxx,

则获取第一个bean使用getBean("xxx"),获取第二个bean使用getBean("xxx#1"),获取第三个bean使用getBean("xxx#2")。

3、依赖注入

3.1、属性注入

(1)属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供Setter方法。spring先调用默认构造函数实例化bean对象,然后通过反射的方式调用Setter方法注入属性值。

(2)spring只会检查bean中是否有对应的Setter方法,至于bean中是否有对应的属性变量则不做要求。

(3)javabean关于属性命名的特殊规范:变量的前2个字母要么全部大写,要么全部小写。

3.2、构造函数注入

(1)构造函数参数的配置顺序不会对配置结果产生影响,spring的配置文件采用和元素标签顺序无关的策略,这种策略可以在一定程度上保证配置信息的确定性。

(2)按索引匹配入参

如果构造函数的入参类型相同,则需要指定参数的顺序索引,否则无法确定对应关系。如:

<constructor-argindex="0"value="xxxxxx">
<constructor-argindex="1"value="xxxxxx">

索引从0开始。

(3)循环依赖问题

如果有2个bean的构造函数配置都依赖对方,则会出现类似线程死锁的问题,

解决的办法就是将构造函数注入改为属性注入。

3.3、工厂方法注入

(1)非静态工厂方法

由于工厂方法不是静态的,所以得先创建一个工厂类的实例bean,并使用factory-bean来引用

<beanid="carFactory"class="工厂类"/>
<beanid="car5"factory-bean="carFactory"factory-method="createCar"/>

(2)静态工厂方法

<beanid="car5"class="工厂类"factory-method="createCar"/>

3.4、注入参数详解

(1)xml中的5个特殊字符


特殊符号

转义序列

特殊符号

转义序列
<
<

""

"
>
>

'

'

&

&

(2)<![CDATA[]]>

<![CDATA[]]>的作用是让XML解析器将标签中的字符串当作普通文本对待。

(3)使用<null/>标签注入null值

(4)级联属性

<beanid="parent"class="xxxxxxx">
<propertyname="child.xxx"value="依赖对象的属性值"/>
</bean>

spring3.0之前,必须先实例化依赖对象child,否则会抛出异常,spring3.0之后,则不需要在显示实例化,spring容器会自动实例化依赖对象。

(5)集合合并

<setmerge="true"/>

常见于子类合并父类的集合元素

(6)通过util命名空间配置集合类型的bean

如果希望配置一个集合类型的Bean,而不是一个集合类型的属性,则可以通过util命名空间进行配置。

3.5、自动装配

(1)<bean/>元素提供了一个指定自动装配类型的属性autowire

3.6、方法注入

如果我们往单例模式的bean中注入prototype的bean,并希望每次调用时都能够返回一个新的bean,使用传统的注入方式将无法实现,因为单例的bean注入关联bean的动作仅发生一次。

(1)一种可选的解决方法就是让宿主bean实现BeanFactoryAware接口,让宿主bean能够访问容器的引用,这样就可以修改get方法,使用容器的

factory.getBean("被依赖bean")方法,每次都能获得最新的bean。

(2)上面那种方式使我们的代码和spring耦合,实为下策,我们可以通过方法注入的方式解耦。

我们只需定义一个接口,接口中定义一个获取依赖bean的抽象方法,spring配置如下:

<beanid="car"class="被依赖bean"/>
<beanid="host"class="接口bean">
<lookup-methodname="getCar"bean="car"/>
</bean>

通过lookup-method元素标签为接口bean的getCar()提供动态实现,方法注入的实现主要依赖Cglib包的动态操作字节码技术。

3.7、方法替换

使用bean2替换bean1的getCar方法,前提是bean2得实现MethodReplacer接口,配置如下:

<beanid="bean1"class="aaaaaaaaaa">
<replaced-methodname="getCar"replacer="bean2"/>
</bean>
<beanid="bean2"class="bbbbbbbbb"/>

4、<bean>之间的关系

4.1、继承

父bean的配置可以被子类继承,避免重复定义,配置如下:

<beanid="父bean"class="aaaaaaa"abstract="true"/>
<beanid="子bean"class="bbbbbb">

子类可以覆盖父类的配置,如果不指定父类的abstract="true",则父bean会被实例化。

4.2、依赖

有些bean的实例化依赖其他bean,其他bean必须先实例化好后才能实例化宿主bean,spring提供了depends-on的属性,指定依赖bean先实例化,如:

<beanid="host"class="aaaaaaa"depends-on="b1"/>
<beanid="b1"class="bbbbbbb"/>

如果有多个前置依赖bean,则可以通过逗号,空格或分号的方式创建bean的名称。

4.3、Bean作用域

(1)spring容器在启动时就会实例化所有的bean,如果不想提前实例化,<bean/>的lazy-init="true"属性可以控制延迟实例化,但是如果该bean被其他需要提前实例化的bean引用,则spring也将忽略延迟实例化的设置。

(2)web应用相关的作用域

如果用户使用request,session,globalSession作用域,首先必须在web容器中进行额外的配置:

在低版本的web容器(Servlet2.3之前),可以使用http请求过滤器配置:

<filter>
    <filter-name>requestContextFilter</filter-name>
    <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>requestContextFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

在高版本的web容器中,可以使用http请求监听器进行配置:

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  </listener>

(3)作用域依赖问题

当将web作用域的bean注入到singleton或prototype的bean中时,要借助于aop,例如:

<bean id="web1" class="aaaaaa" scope="request" >
  <aop:scoped-proxy/>
</bean>
<bean id="singleton1" class="bbbbbb" >
  <property name="z1" ref="web1" />
</bean>

4.4、FactoryBean

一般情况下,spring通过反射机制利用<bean/>的class属性指定实现类实例化bean就可以了。但在某些情况下,实例化bean的过程比较复杂,如果按照传统的方式,则需要在<bean>中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。

Spring为此提供了一个org.springframework.beans.factory.FactoryBean工厂类接口,用户可以通过实现该接口,定制实例化bean的逻辑。

当<bean/>的class属性配置的实现类是FactoryBean及其子类时,通过getBean()方法返回的不是FactoryBean及其子类本身,而是返回FactoryBean的getObject()方法返回的对象。

如果希望获取FactoryBean及其子类本身的对象,则在getBean(beanName)方法时显式地在beanName前加上“&”前缀,如getBean("&car5")。

5、基于注解的配置

5.1、注解类型

@Component------原生注解

衍型注解:

@Repository:标注DAO

@Service:标注service

@Controller:标注控制器

5.2、使用注解配置信息启动spring容器

(1)spring2.5以后引入了context命名空间,它提供了通过扫描类包以应用注解定义bean:

<context:component-scan base-package="xxxxxxxxxx" resource-pattern="xxxx/*.class">

resource-pattern属性用于指定在基包中需要扫描的特定包下的类

(2)还有更加强大过滤子标签

<context:component-scan base-package="xxxxxxxxxx" >
  <context:include-filter type="xxxx" expression="xxxxxxxxxxxxxxxx"/>
  <context:exclude-filter type="xxxx" expression="xxxxxxxxxxxxxxxx"/>
</context:component-scan>

在所有的类型中,aspectj的过滤能力是最强大的。

5.3、自动装配Bean

(1)@Autowired

@Autowired默认按类型匹配的方式,如果容器中没有一个匹配的bean,spring容器启动时将抛出异常,那么可以使用@Autowired(required=false)进行标注,则不会抛出异常。

使用@Autowired还可以对方法入参直接标注,如果一个方法有多个入参,在默认情况下,spring自动选择匹配入参类型的bean进行注入。

使用@Autowired标注集合变量,可以将所有匹配该集合元素类型的bean都注入进来,很强大。

使用@Autowired装配属性,可以没有setter方法。

(2)@Qualifiler

如果容器中有一个以上匹配的bean,则可以通过@Qualifiler注解限定bean的名称。

(3)对标注注解的支持

spring还支持JSR-250定义的@Resource和JSR-330定义的@Inject注解

@Resource要求提供一个bean的名称属性,如果属性为空,则自动采用变量名或者方法名作为bean的名称。

(4)要点:

如果仅仅使用@Autowired,我们仍然需要显式地在xml中定义<bean/>节点,spring容器默认禁用注解装配,启用的方式是在xml中配置<context:annotation-config/>元素。

但是spring还提供了另一种技巧,使用<context:component-scan/>元素,spring容器就会自动检测bean,而不需要显式的定义<bean/>节点。

spring通过@Component、@Repository、@Service、@Controller注解标注类,让<context:component-scan/>知道哪些类需要注册为SpringBean。

如果使用了第三方的jar包,且希望自动注入第三方jar包中的类,即使第三方jar包的类中没有使用注解标注它们,过滤器元素<context:include-filter>可以替换掉基于注解的组件扫描策略,让<context:component-scan/>自动注册符合expression表达式的类。

5.4、Bean作用范围及生命过程方法

(1)@Scope("xxxx")

通过注解配置的Bean和通过xml配置的Bean一样,默认的作用范围都是singleton。

spring提供了@Scope注解,作用于类上,注解的参数就和xml中<bean/>的scope属性的值一样。

(2)生命过程方法对比


<bean>
注解

init-method

@PostConstruct

destory-method

@PreDestroy

区别:注解在类中可以定义多个方法,且方法按顺序执行

6、基于java类的配置

6.1、使用java类提供Bean定义信息

(1)普通的POJO只要标注@Configuration注解,就可以为spring容器提供bean定义的信息,每个标注了@Bean的方法都相当于提供一个Bean的定义信息。

(2)@Bean

Bean的类型由@Bean标注的方法的返回值类型决定

Bean的名称默认和方法名相同,也可以通过@Bean(name="xxx")来显式指定

可以在@Bean处使用@Scope,标注Bean的使用范围

(3)@Configuration

由于@Configuration注解类本身已经标注了@Component注解,所以任何标注了@Configurstion的类,都可以使用@Autowired被自动装配到其他类中。

6.2、使用基于java类的配置信息启动spring容器

(1)spring提供了一个AnnotationConfigApplicationContect类,它能够直接通过标注@Configuration注解的类启动Spring容器。

(2)当有多个配置类时

可以通过AnnotationConfigApplicationContect的register方法一个个注册,然后再调用refresh方法刷新容器以应用这些注册的配置类。

也可以通过@Import(xxx.class)注解,将其他配置类全部引入到一个配置类中,这样仅需要注册一个配置类即可

(3)通过xml配置类引用@Configuration的配置

<context:component-scanbase-package="......"resource-pattern="配置类名">

(4)在配置类中引用xml配置信息

在@Configuration处使用@ImportResource("classpath:................")来引入xml配置文件

6.3、3种配置方式的比较


XML

注解

java类
  • 适用于Bean的实现类来源于第三方类库,如DataSource、JdbcTemplate等,因无法在类中标注注解
  • 命名空间,如aop等

Bean的实现类是当前项目开发

通过代码方式控制Bean初始化整体逻辑,适用于实例化Bean比较复杂的场景

总结

以上就是本文关于spring在IoC容器中装配Bean详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:

Spring 3.x中三种Bean配置方式比较详解

浅谈Spring单例Bean与单例模式的区别

Spring配置使用之Bean生命周期详解

如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

(0)

相关推荐

  • Spring实例化bean的方式代码详解

    通过这篇文章通过实例代码向大家介绍了Spring实例化bean的几种方法,接下来看看具体内容吧. 1.使用类构造器实现实例化(bean的自身构造器) <bean id = "orderService" class="cn.itcast.OrderServiceBean"/> 2.使用静态工厂方法实现实例化 <bean id = "personService" class = "cn.itcast.OrderFactor

  • Spring循环依赖正确性及Bean注入的顺序关系详解

    一.前言 我们知道 Spring 可以是懒加载的,就是当真正使用到 Bean 的时候才实例化 Bean.当然也不全是这样,例如配置 Bean 的 lazy-init 属性,可以控制 Spring 的加载时机.现在机器的性能.内存等都比较高,基本上也不使用懒加载,在容器启动时候来加载bean,启动时间稍微长一点儿,这样在实际获取 bean 供业务使用时,就可以减轻不少负担,这个后面再做分析. 我们使用到 Bean 的时候,最直接的方式就是从 Factroy 中获取,这个就是加载 Bean 实例的源

  • Spring学习笔记之bean生命周期

    前言 上一篇文章主要学习了下bean的配置.注入.自定义属性编辑器,今天来熟悉bean的生命周期. 任何一个事物都有自己的生命周期,生命的开始.生命中.生命结束.大家最熟悉的应该是servlet 的生命周期吧.和 servlet 一样 spring bean 也有自己的生命周期. 在开发中生命周期是一个很常见的名词,基本每种编程语言都能找到与它关联的.关于bean的生命周期我在网上也找了好多,基本都差不多.这里我主要是想通过代码来验证,毕竟学的知识都是一样的,都是学的Java,最重要的是动手练习

  • 浅谈Spring单例Bean与单例模式的区别

    Spring单例Bean与单例模式的区别在于它们关联的环境不一样,单例模式是指在一个JVM进程中仅有一个实例,而Spring单例是指一个Spring Bean容器(ApplicationContext)中仅有一个实例. 首先看单例模式,在一个JVM进程中(理论上,一个运行的JAVA程序就必定有自己一个独立的JVM)仅有一个实例,于是无论在程序中的何处获取实例,始终都返回同一个对象,以Java内置的Runtime为例(现在枚举是单例模式的最佳实践),无论何时何处获取,下面的判断始终为真: // 基

  • Spring 3.x中三种Bean配置方式比较详解

    以前Java框架基本都采用了XML作为配置文件,但是现在Java框架又不约而同地支持基于Annotation的"零配置"来代替XML配置文件,Struts2.Hibernate.Spring都开始使用Annotation来代替XML配置文件了:而在Spring3.x提供了三种选择,分别是:基于XML的配置.基于注解的配置和基于Java类的配置. 下面分别介绍下这三种配置方式:首先定义一个用于举例的JavaBean. package com.chinalife.dao public cl

  • Spring学习笔记之bean的基础知识

    Bean: 在Spring技术中是基于组件的 最基本了是最常用的单元 其实实例保存在Spring的容器当中 Bean通常被定义在配置文件当中,Bean实例化由Spring的Ioc容器进行管理,Bean的实例可以通过Beanfactory进行访问,实际上大部分J2EE应用,Bean是通过ApplicationContext来访问的,ApplicationContext是BeanFactory的子接口,功能要比BeanFactory强大许多 在前面得博客依赖注入与控制反转中演示了应用spring实现

  • Spring @Bean vs @Service注解区别

    今天跟同事讨论了一下在Spring Boot中,是使用@Configuration和@Bean的组合来创建Bean还是直接使用 @Service等注解放在类上的方式.笔者倾向于使用第一种,即@Configuration和@Bean的组合. 先来看一个例子,目标是创建SearchService的一个Bean. 直接使用@Service的方式: // SearchService.java package li.koly.search; import java.util.List; public in

  • Spring中实例化bean的四种方式详解

    前言 在介绍Bean的实例化的方式之前,我们首先需要介绍一下什么是Bean,以及Bean的配置方式. 如果把Spring看作一个大型工厂,那么Spring容器中的Bean就是该工厂的产品.要想使用Spring工厂生产和管理Bean,就需要在配置文件中指明需要哪些Bean,以及需要使用何种方式将这些Bean装配到一起. Spring容器支持两种格式的配置文件,分别为Properties文件格式和xml文件格式,而在实际的开发当中,最常使用的额是xml文件格式,因此在如下的讲解中,我们以xml文件格

  • spring在IoC容器中装配Bean详解

    1.Spring配置概述 1.1.概述 Spring容器从xml配置.java注解.spring注解中读取bean配置信息,形成bean定义注册表: 根据bean定义注册表实例化bean: 将bean实例放入bean缓存池: 应用程序使用bean. 1.2.基于xml的配置 (1)xml文件概述 xmlns------默认命名空间 xmlns:xsi-------标准命名空间,用于指定自定义命名空间的schema文件 xmlns:xxx="aaaaa"-------自定义命名空间,xx

  • spring定义和装配bean详解

    在阅读本文之前,大家可先参阅<简单理解Spring之IOC和AOP及代码示例>一文,了解下Spring中IOC和AOP的相关内容.下面进入正题.本篇文章介绍在Spring中如何定义和装载Java Bean. 业务场景 还是人开车的例子.首先,定义一个Car接口和两个实现了Benz和BMW,然后定义一个Person类,Person类依赖Car接口. public interface Car { void go(); } public class Benz implements Car { pub

  • 向Spring IOC 容器动态注册bean实现方式

    目录 本文的大纲 从一个需求谈起 Spring Bean的生命周期再完善 BeanDefinition Bean 加入IOC容器的几种方式 从spring容器中动态添加或移除bean 本文的大纲 从一个需求谈起 这周遇到了这样一个需求,从第三方的数据库中获取值,只是一个简单的分页查询,处理这种问题,我一般都是在配置文件中配置数据库的地址等相关信息,然后在Spring Configuration 注册数据量连接池的bean,然后再将数据库连接池给JdbcTemplate, 但是这种的缺陷是,假设填

  • Spring为IOC容器注入Bean的五种方式详解

    这篇文章主要介绍了Spring为IOC容器注入Bean的五种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一 @Import导入组件,id默认是组件的全类名 //类中组件统一设置.满足当前条件,这个类中配置的所有bean注册才能生效: @Conditional({WindowsCondition.class}) @Configuration @Import({Color.class,Red.class,MyImportSelector

  • 详解Spring简单容器中的Bean基本加载过程

    本篇将对定义在 XMl 文件中的 bean,从静态的的定义到变成可以使用的对象的过程,即 bean 的加载和获取的过程进行一个整体的了解,不去深究,点到为止,只求对 Spring IOC 的实现过程有一个整体的感知,具体实现细节留到后面用针对性的篇章进行讲解. 首先我们来引入一个 Spring 入门使用示例,假设我们现在定义了一个类 org.zhenchao.framework.MyBean ,我们希望利用 Spring 来管理类对象,这里我们利用 Spring 经典的 XMl 配置文件形式进行

  • IOC 容器启动和Bean实例化两个阶段详解

    目录 IOC 容器的两个阶段 容器启动阶段 Bean 实例化阶段 插手容器的启动 PropertyPlaceholderConfigurer 占位符机制 PropertyOverrideConfigurer 重写属性值 实例-使用容器扩展点修改 BeanDefinition IOC 容器的两个阶段 IOC 容器可以分为两个阶段 : 容器启动阶段和 Bean 实例化阶段. Spring 的 IoC 容器在实现的时候, 充分运用了这两个阶段的不同特点, 在每个阶段都加入了相应的容器扩展点, 支持开发

  • Spring IoC学习之ApplicationContext中refresh过程详解

    refresh() 该方法是 Spring Bean 加载的核心,它是 ClassPathXmlApplicationContext 的父类 AbstractApplicationContext 的一个方法 , 顾名思义,用于刷新整个Spring 上下文信息,定义了整个 Spring 上下文加载的流程. public void refresh() throws BeansException, IllegalStateException { synchronized(this.startupShu

  • Spring注解实现Bean自动装配示例详解

    何为自动装配 自动装配是 Spring 满足 bean 依赖的一种方式. 在使用 Spring 配置 bean 时,我们都要给配置的 bean 的属性设置一个值,如果不手动设置则都是空.而自动的好处就在于,我们不用手动去设置一个值,spring 会在上下文中自动寻找并装配合适的值. 本文主要介绍了Spring注解Bean自动装配的相关内容,下面话不多少了,来一起看看详细的介绍吧 使用须知: 1.导入约束:context约束 2.配置注解的支持: context:annotation-config

  • Spring框架IOC容器底层原理详解

    目录 1.什么是IOC 2.IOC容器的底层原理 3.那么上边提到的三种技术如何实现IOC的呢 4.IOC(接口) 1.什么是IOC IOC – Inverse of Control,控制反转,将对象的创建权力反转给Spring框架! 在java当中一个类想要使用另一个类的方法,就必须在这个类当中创建这个类的对象,那么可能会出现如下情况, 比如A类当中创建着B对象,B类当中有C对象,C类当中有A对象,这个如果一个类出了问题,那么可能会导致这个框架出现问题. Spring 将创建对象的权利给了IO

  • Spring Bean常用的的装配方式详解

    Bean常用的装配方式有3种: 基于xml的装配 基于Annotation(注解)的装配 基于Java配置类的装配 基于xml的装配 在xml文件中配置Bean. 如果依赖很多,xml配置文件会很臃肿,后期维护.升级不方便.自动装配可解决这一问题. 基于xml的自动装配 在<bean>中使用autowired属性完成依赖的自动装配,不再使用<property>手动注入setter方法中的依赖,简化了配置,减少了xml中的代码量. autowire属性的属性值: no 不使用自动装配

随机推荐