Spring:Bean

Spring笔记(二)


 

Spring中Bean的配置

  在Spring中,XML配置文件的根元素是,它其中可以包含多个子元素,每一个子元素定义一个Bean,并且描述该Bean如何被装配到Spring容器中。子元素包含多个属性和子元素,常用的属性和子元素如下表:

属性或子元素名称 说明
id Bean的唯一标识符,Spring容器对Bean的配置、管理都是通过该属性进行
name name属性可以为Bean指定多个名称,每个名称之间用逗号或者分号隔开
class 指定Bean的实现类,必须使用全限定名称
scope 用于设置Bean实例的作用域,默认为单例singleton
constructor-arg

元素的子元素,可以使用此元素传入构造参数进行实例化。该元素的index属性指定构造参数的序号(从0开始),type属性指定构造参数的类型,参数值可以通过ref属性或者value属性值来指定,也可以通过ref或value子元素指定

property

元素的子元素,用于调用Bean实例中的setter()方法完成属性赋值,从而完成依赖注入。该元素的name属性指定Bean实例中的相应属性名,ref属性或value属性用于指定参数值

ref

等元素的属性或者子元素,用于指定在Bean工厂中对某个Bean实例的引用

value 等元素的属性或者子元素,用于直接给定一个常量值
list 用于封装List或数组属性的依赖注入
set 用于封装Set类型属性的依赖注入
map 用于封装Map类型属性的依赖注入
entry

元素的子元素,用于设置一个键值对。其key属性指定字符串类型的键值,ref属性或value属性直接指定其值,也可以通过ref或value子元素进行指定值

 

  在Spring的配置文件中,通常一个普通的Bean只需要定义id(或者name)和class两个属性即可。定义Bean的方式如下:  

    
    
    <bean id="bean1" class="com.ssm.Bean1"/>
    
    <bean name="bean2" class="com.ssm.Bean2"/>
View Code

  如果在Bean中既没有指定id,也没有指定name,那么Spring会将class值当作id使用。

Bean的作用域

  Spring 4.3中为Bean的实例定义了种作用域,其中最常用的是singleton和prototype。在Spring中,Bean的作用域是通过元素的scope属性来指定的。其余见下图:

     Spring:Bean_第1张图片

  singleton作用域

    singleton是Spring容器默认的作用域,当Bean的作用域为singleton 时,Spring容器就只会存在一个共享的 Bean 实例,并且所有对Bean的请求, 只要 id与该Bean的id属性相匹配, 就会返回同一个 Bean的实例。 singleton作用域对于无会话状态的 Bean( 如Dao组件、Service组件)来说是最理想的选择。

    1.使用idea创建一个简单的web项目,在pom文件中加入依赖,pom文件代码如下:

xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>com.soai.demogroupId>
    <artifactId>testartifactId>
    <version>1.0-SNAPSHOTversion>
    <packaging>warpackaging>

    <dependencies>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-coreartifactId>
            <version>4.3.16.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-context-supportartifactId>
            <version>4.3.16.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>4.3.16.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-expressionartifactId>
            <version>4.3.16.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-aopartifactId>
            <version>4.3.16.RELEASEversion>
        dependency>
        <dependency>
            <groupId>commons-logginggroupId>
            <artifactId>commons-loggingartifactId>
            <version>1.2version>
        dependency>
    dependencies>
project>
View Code

    2.在com.soai.demo包下建立Scope、ScopeTest类

package com.soai.demo;

public class Scope {
    
}
View Code
package com.soai.demo;

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

public class ScopeTest {

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

        for (int i = 0; i < 10; i++) {
            System.out.println("第" + i + "次Scope实例地址:" + applicationContext.getBean("scope"));
        }
    }
}
View Code

    3.在resources目录下配置applicationContext.xml


       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.xsd ">

    
    class="com.soai.demo.Scope"/>

View Code

    4.运行ScopeTest,在控制台中姐可以看到10次取到的实例对象都是同一个,这就说明Spring容器只创建了一个Scope类的实例:

      Spring:Bean_第2张图片

  prototype作用域

    对需要保持会话状态的Bean应用使用prototype作用域。在使用prototype作用域时,Spring容器会为每个对该 Bean的请求 都创建一个新的实例。
    修改上面applicationContext.xml为:


<bean id="scope" class="com.soai.demo.Scope" scope="prototype"/>
View Code

    此时再次运行ScopeTest,可以看出10次输出的Bean实例并不相同,这说明在prototype作用域下创建了10个不同的Scope实例。运行结果为:

      Spring:Bean_第3张图片

Bean的装配方式

  Bean的装配可以理解为依赖关系注入,Bean的装配方式即Bean依赖注入的方式。Spring容器支持多种方式的Bena装配,例如基于XML的装配、基于Annoation(注解)的装配、自动装配等等。

  1.基于XML的装配

    Spring提供了两种基于XML的装配方式:设值注入(SetterInjection)和构造注入(ConstructorInjection)。

    在Spring实例化Bean的过程中,Spring首先会调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用setter()方法来注入属性值。因此,设值注入要求一个Bean必须满足以下两点要求: 

      a.Bean类必须提供一个默认的无参构造方法。 

      b.Bean类必须为需要注入的属性提供对应的setter()方法。

    使用设值注入时,在Spring配置文件中需要使用元素的子元素来为每个属性注入值;

    而使用构造注入时,在配置文件中需要使用元素的子元素来定义构造方法的参数,可以使用其value属性(或子元素)来设置该参数的值。

    案例:

      a.创建User类:

package com.soai.demo02;

import java.util.List;

public class User {

    private String userName;
    private String password;
    private List stringList;

    /**
     *使用构造注入
     * 提供带所有参数的构造方法
     */
    public User(String userName, String password, List stringList) {
        this.userName = userName;
        this.password = password;
        this.stringList = stringList;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                ", stringList=" + stringList +
                '}';
    }
    /**
     * 使用设值注入
     * 提供默认空参构造方法
     * 为所有属性提供setter方法
     */
    public User() {
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setStringList(List stringList) {
        this.stringList = stringList;
    }
}
View Code

      b.spring配置文件中分别装配按照设值注入和构造注入的两个User实例的Bean


    <bean id="user1" class="com.soai.demo02.User" scope="prototype">
        <constructor-arg index="0" value="张三"/>
        <constructor-arg index="1" value="123456"/>
        <constructor-arg index="2">
            <list>
                <value>"这是value1"value>
                <value>"这是value2"value>
            list>
        constructor-arg>

    bean>

    
    <bean id="user2" class="com.soai.demo02.User">
        <property name="userName" value="李四"/>
        <property name="password" value="654321"/>
        <property name="stringList">
            <list>
                <value>"这是value3"value>
                <value>"这是value4"value>
            list>
        property>
    bean>
View Code

      c.运行测试类:UserTest

package com.soai.demo02;

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

public class UserTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println(applicationContext.getBean("user1"));
        System.out.println(applicationContext.getBean("user2"));
    }
}
View Code

      d.测试结果:已经成功的使用基于XML装配的构造注入和设值注入两种方式装配了User实例。

  2.基于Annotation的装配

    在Spring中,尽管使用XML配置文件可以实现Bean的装配工作,但如果应用中有很多Bean,就会导致XML配置文件过于臃肿,给以后的维护和升级工作带来一定的困难。为此,Spring提供了对Annotation(注解)技术的全面支持。

    Spring中常用的注解:

      a.@Component:可以使用此注解描述Spring中的Bean。但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需要将该注解标注在类上即可。

      b.@Repository:用于数据访问层(Dao层)的类标识为Spring中的Bean,其功能与@Component

      c.@Service:经常作用在业务层(Service层),用于将业务层的类标识为Spring中的Bean,其功能与@Component

      d.@Controller:经常作用在控制层(Spring MVC中的Controller),用于将控制层的类标识为Spring中的Bean,其功能与@Component

      e.@Autowired(Spring的注解):用于对Bean的属性变量、属性的setter()方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动装配工作。默认是按照Bean的类型(byType)进行装配,不会去匹配name。

      f.@Resource(java的注解):起作用与@Autowired一样,区别在于@Autowired默认是按照Bean类型来装配,而@Resource默认是按照Bean实例名称进行装配。@Resource有两个重要的属性:name和type。Spring将name解析成为Bean实例名称,type属性解析为Bean实例类型。 若指定name属性,则按照实例名称进行装配;

           若指定type,则按照Bean类型进行装配;

           若都不指定,则先按Bean实例名称装配,不能匹配时再按照Bean类型进行装配

           若都无法匹配,则抛出NoSuchBeanDefinitionException异常

      g.@Qualifier:与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名称装配,Bean的实例名由@Qualifier注解的参数指定

      注意:虽然@Repository、@Service和@Controller的功能与@Component注解的功能相同,但为了使标注类本身用途更加清晰,建议在实际开发中使用@Repository、@Service和@Controller分别对实现类进行标注。在接口仅有单一实现类时,@Autowired与@Resource两个注解的修饰效果相同,可以互相替换,不影响使用。

    与基于XML方式的注解不同的是:在元素中包含了context的约束信息,除此之外,要使用context命名空间在配置文件中开启相应的注解处理器,而此时再定义Bean实例的时候,就不再需要配置子元素

    使用注解装配Bean的方式一定程度上减少了配置文件中的代码量。

  3.自动装配

    如何再以上装配方式的情况下,继续再次减少代码量呢?Spring中的元素中包含一个autowire属性,通过设置该属性的值来自动装配Bean。所谓的自动装配就是将一个Bean自动注入其他Bean的property中。

    元素的autowire属性值及说明:

      a.default:由的default-autowire属性值确定

<--其子元素>的autowire属性对应的属性值也是byName-->
<beans default-autowire="byName">
View Code

      b.byName:根据属性的名称自动装配。容器按照名称查找与属性完全一致的Bean,并将其属性自动装配

      c.byType:根据属性的数据类型自动装配,如果一个Bean的数据类型兼容另一个Bean中属性的数据类型(兼容包括继承和接口实现类),则自动装配

      d.constructor:根据构造函数参数的数据类型进行byType模式的自动装配

      e.no:在默认情况下,不使用自动装配,Bean依赖必须通过ref元素定义

End

你可能感兴趣的:(Spring:Bean)