Spring -- Bean自动装配&Bean之间关系&Bean的作用域

Bean的自动装配

Spring IOC 容器可以自动装配 Bean. 需要做的仅仅是在 的 autowire 属性里指定自动装配的模式

有以下几种自动装配的类型:

  • byType(根据类型自动装配): 若 IOC 容器中有多个与目标 Bean 类型一致的 Bean. 在这种情况下, Spring

    将无法判定哪个 Bean 最合适该属性, 所以不能执行自动装配.

  • byName(根据名称自动装配): 必须将目标 Bean 的名称和属性名设置的完全相同.
  • constructor(通过构造器自动装配): 当 Bean 中存在多个构造器时, 此种自动装配方式将会很复杂. 不推荐使用

首先我们先来看一个手动装配的例子,

目录结构

先创建两个实体Bean

package com.gp.spring.autowire;

public class Person {
    private String name;
    private Address address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", address=" + address + "]";
    }

}
package com.gp.spring.autowire;

public class Address {
    private String city;
    private String street;

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    @Override
    public String toString() {
        return "Address [city=" + city + ", street=" + street + "]";
    }

}

再创建IOC配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-4.0.xsd">

    <bean id="address" class="com.gp.spring.autowire.Address"
        p:city="beijing" p:street="haidian"></bean>

    <bean id="person" class="com.gp.spring.autowire.Person"
        p:name="Alis" p:address-ref="address"></bean>
</beans>

测试代码

package com.gp.spring.autowire;

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

public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "autowired.xml");
        Person p = (Person) ctx.getBean("person");

        System.out.println(p);
    }
}

输出结果

Person [name=Alis, address=Address [city=beijing, street=haidian]]



下面我们来看一下是如何进行自动装配的

修改配置文件

    <bean id="address" class="com.gp.spring.autowire.Address"
        p:city="beijing" p:street="haidian"></bean>

    <bean id="person" class="com.gp.spring.autowire.Person"
        p:name="Alis" autowire="byName"></bean>

增加代码autowire=”byName”,使用byName的方式进行自动匹配。

它就会根据person类中的setAddress属性匹配名为address的bean。

同理可知,byType匹配方式,匹配与setAddress类型一直的bean。


XML 配置里的 Bean 自动装配的缺点

  • 在 Bean 配置文件里设置 autowire 属性进行自动装配将会装配 Bean 的所有属性. 然而, 若只希望装配个别属性时,

    autowire 属性就不够灵活了.

  • autowire 属性要么根据类型自动装配, 要么根据名称自动装配, 不能两者兼而有之.
  • 一般情况下,在实际的项目中很少使用自动装配功能,因为和自动装配功能所带来的好处比起来,明确清晰的配置文档更有说服力一些

Bean的继承关系

  • Spring 允许继承 bean 的配置, 被继承的 bean 称为父 bean. 继承这个父 Bean 的 Bean 称为子 Bean
  • 子 Bean 从父 Bean 中继承配置, 包括 Bean 的属性配置
  • 子Bean也可以覆盖从父Bean中继承过来的属性
  • 父 Bean 可以作为配置模板, 也可以作为 Bean 实例. 若只想把父 Bean 作为模板, 可以设置 bean的abstract 属性为 true, 这样 Spring 将不会实例化这个 Bean

来看下下面这段代码

    <bean id="address1" class="com.gp.spring.autowire.Address"
        p:city="鸡西" p:street="南岗"></bean>

    <bean id="address2" class="com.gp.spring.autowire.Address"
        p:city="鸡西" p:street="电台路"></bean>
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "context_relate.xml");
        Address address = (Address) ctx.getBean("address1");
        System.out.println(address);

        address = (Address) ctx.getBean("address2");
        System.out.println(address);
    }

输出结果

Address [city=鸡西, street=南岗]

Address [city=鸡西, street=电台路]

很简单的属性注入,你是否注意到再配置文件中,注入的两条信息,大部分内容是相同的,比如相同的Bean,相同的值。

这里我们可以用一个Bean继承的做法,来简化配置,如下

    <bean id="address1" class="com.gp.spring.autowire.Address"
        p:city="鸡西" p:street="南岗"></bean>

    <bean id="address2" p:street="电台路" parent="address1"></bean>

这里用到了parent,继承自address1的Bean,然后我们在重写我们要修改的内容。


抽象Bean(abstract=”true”)

抽象的Bean是不允许被实例化的,我们看一个错误的代码

    <bean id="address1" class="com.gp.spring.autowire.Address"
        p:city="鸡西" p:street="南岗" abstract="true"></bean>

    <bean id="address2" p:street="电台路" parent="address1"></bean>

address1增加了abstract=”true”表示为抽象Bean

    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "context_relate.xml");
        Address address = (Address) ctx.getBean("address1");
        System.out.println(address);

        address = (Address) ctx.getBean("address2");
        System.out.println(address);
    }

运行测试方法

我们会看到以下异常,意思为抽象类是不许被实现的。

Exception in thread “main” org.springframework.beans.factory.BeanIsAbstractException: Error creating bean with name ‘address1’: Bean definition is abstract

所以我们去掉address1的实现即可。

    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "context_relate.xml");
//      Address address = (Address) ctx.getBean("address1");
//      System.out.println(address);

        Address address = (Address) ctx.getBean("address2");
        System.out.println(address);
    }

通常抽象Bean用法,不指定具体的类,在其继承的子类中指定class,如下

    <bean id="address1" p:city="鸡西" p:street="南岗" abstract="true"></bean>

    <bean id="address2" class="com.gp.spring.autowire.Address"
        p:street="电台路" parent="address1"></bean>

    <bean id="address3" class="com.gp.spring.autowire.Address"
        p:street="和平大街" parent="address1"></bean>

依赖Bean的配置

当我们在注入Bean的信息的时候,如果要求某些信息必须录入,则这就是Bean的依赖。

比如我们注入一个person类信息,其中person有一个address的属性,前提要求address必须要被注入数据,这样这个人才有地址,也就是person依赖address

下面我们来看看代码

    <bean id="address" class="com.gp.spring.autowire.Address"
        p:street="和平大街" p:city="鸡西"></bean>

    <bean id="person" class="com.gp.spring.autowire.Person"
        p:name="pengpeng" depends-on="address"></bean>

输出内容

Person [name=pengpeng, address=null]

如果我们去掉address

    <!--
    <bean id="address" class="com.gp.spring.autowire.Address"
        p:street="和平大街" p:city="鸡西"></bean>
     -->
    <bean id="person" class="com.gp.spring.autowire.Person"
        p:name="pengpeng" depends-on="address"></bean>

会抛出一下异常

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named ‘address’ is defined

如果前置依赖于多个 Bean,则可以通过逗号,空格或的方式配置 Bean 的名称


Bean的作用域

Bean的作用域可以理解为IOC容器中的Bean他的作用范围,我们通过以上的内容了解到获取到一个bean的信息通过以下方式

Address address1 = (Address) ctx.getBean("address");

那比如现在我获取多个的时候会是什么样子的呢,我们做了下测试

    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "context_relate.xml");
        Address address1 = (Address) ctx.getBean("address");
        Address address2 = (Address) ctx.getBean("address");
        System.out.println(address1 == address2);
    }

输出结果:true

可知IOC容器中的Bean都是单实例的。

我们可以通过scope来配置Bean的作用域,目前有四种

其中主要用的singleton、prototype。默认情况是singleton。

下面修改IOC配置

    <bean id="address" class="com.gp.spring.autowire.Address"
        p:street="电台路" p:city="鸡西" scope="prototype"></bean>

输出结果:false

另外两个request、session在web的应用开发中使用。后续用到的时候单独介绍。


使用外部属性文件

我们在开发的时候会使用spring注入JDBC的连接池信息,代码如下

<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"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">

    <context:property-placeholder location="classpath:db.properties"/>

    <bean id="db" class="com.gp.spring.jdbc.DataSource">
        <property name="userName" value="${username}"></property>
        <property name="password" value="${password}"></property>
    </bean>
</beans>

这里context:property-placeholder引入外部文件,然后通过${}方式获取信息。

db.properties代码如下

username=root
password=123456

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-20 12:52:54

Spring -- Bean自动装配&Bean之间关系&Bean的作用域的相关文章

3.spring:自动装配/Bean之间的关系/作用域/外部文件/spel/

1.自动装配/手动装配 xml配置文件里的bean自动装配 Spring IOC 容器里可以自动的装配Bean,需要做的仅仅是在<bean>的autowire属性里面指定自动装配模式 ->byType(根据类型自动进行装配):若IOC容器里需要有多个与目标Bean类型一样的Bean,在这种情况子下,Spring无法判定那个Bean合适,所以不能执行自动装配 ->byName(根据名称自动装配):必须将目标Bean的名称和属性名设置完全相同, ->constuuctor(通过是

Spring之自动装配bean

Spring之自动装配bean 最近学习Spring框架,参考资料是Spring IN ACTION----第一张内容飘过去~~ 从第二章的自动装配bean开始,不过学习Spring核心最重要的还是ioc的注入模式吧! 书上是这么说的----(概念问题,哈哈),首先普及几个概念 --------------------------------------------------------------------------------------------------------------

spring中自动装配bean

首先用@Component注解类: package soundsystem: import org.springframework.stereotype.Component; @Component public class TestBean{ …… } 开启组件扫描spring才能自动装配bean,创建一个@ComponentScan注解的类 package soundsystem: import org.springframework.context.annotation.componentS

Spring学习四、Bean自动装配与注解开发

七.Bean的自动装配 自动装配是Spring满足bean依赖的一种方式! Spring会在上下文中自动寻找bean,自动装备属性 在Spring中有三种自动装配方式 在xml中显示配置 在Java中显示配置 隐式的自动装配[重要] 7.1 测试 环境搭建:一个人两个宠物 7.2 ByName自动装配 <!-- ByName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid --> <bean id="people" class="c

Bean自动装配-XML最小化配置

上一个讲了怎样用xml配置所有的Bean以及进行依赖注入,但是这样太麻烦了,对于每一个bean都要写一个xml,可以有几种方式进行自动装配. 四种装配方式 byName(通过名字装配,这时属性的名字必须与bean名字一致) byType(通过类型,匹配与interface或class相同的类型),这种是找到对应的方法,然后进行setter方法进行注入的 constructor(也是通过类型匹配,但是是通过new的进行装配的) 最佳自动装配(先用constructor装配,然后再用byType)

XML 配置里的 Bean 自动装配

在XML文件中,先看一下下面的代码: <bean id="student" class="com.jeremy.spring.beans.student"> <property name="s_name" value="jeremy"></property> <property name="age" value="20"></prop

spring boot 自动装配的实现原理和骚操作,不同版本实现细节调整,debug 到裂开......

开篇说明: 注解本身并没有什么实际的功能(非要说标记也是一个“实际”的功能的话,也可以算吧),隐藏在背后的注解处理器才是实现注解机制的核心.本篇将从这两个层面出发探索 spring boot 自动装配的秘密,并使用 spring boot 的自动装配机制来实现自动装配. 本次代码已经放到 github:https://github.com/christmad/code-share/tree/master/spring-boot-config-practice 代码中主要是做了 @Configur

spring的自动装配,骚话@Autowired的底层工作原理

前言 开心一刻 十年前,我:我交女票了,比我大两岁.妈:不行!赶紧分! 八年前,我:我交女票了,个比我小两岁,外地的.妈:你就不能让我省点心? 五年前,我:我交女票了,市长的女儿.妈:别人还能看上你?分了吧! 今年,我挺着大肚子踏进家门.妈:闺女啊,你终于开窍了 ! 前情回顾 Spring拓展接口之BeanPostProcessor,我们来看看它的底层实现中讲到了spring对BeanPostProcessor的底层支持,并且知道了BeanPostProcessor的两个方法:postProce

Eureka 系列(03)Spring Cloud 自动装配原理

Eureka 系列(03)Spring Cloud 自动装配原理 [TOC] 本文主要是分析 Spring Cloud 是如何整合 Eureka 的,但不会具体分析 Eureka 的源码,之后的文章会对 Eureka 的源码做一个比较具体的分析. 1. Eureka Client 自动装配 org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.cloud.netflix.eureka.