Spring4深入理解01----Bean配置

来源:互联网 发布:linux下timeout 编辑:程序博客网 时间:2024/05/06 12:17

参考代码下载github:https://github.com/changwensir/java-ee/tree/master/spring4

Spring是什么?

    Spring 是一个开源框架.
    Spring 为简化企业级应用开发而生.
    使用 Spring 可以使简单的 JavaBean 实现以前只有 EJB 才能实现的功能. 
    Spring 是一个 IOC(DI) 和 AOP 容器框架.

具体描述 Spring: 
  --轻量级:Spring 是非侵入性的 - 基于 Spring 开发的应用中的对象可以不依赖于 Spring 的API
  --依赖注入(DI --- dependency injection、IOC)
  --面向切面编程(AOP --- aspect oriented programming)
  --容器: Spring 是一个容器, 因为它包含并且管理应用对象的生命周期
  --框架: Spring 实现了使用简单的组件配置组合成一个复杂的应用. 在 Spring 中可以使用 XML 和 Java 注解组合这些对象
  --一站式:在 IOC 和 AOP 的基础上可以整合各种企业应用的开源框架和优秀的第三方类库 (实际上 Spring 自身也提供了展现层的 SpringMVC 和 持久层的 Spring JDBC)



只要后面是Spring IDE就行了

把以下 jar 包加入到工程的 classpath 下:


   Spring 的配置文件: 一个典型的 Spring 项目需要创建一个或多个 Bean 配置文件, 这些配置文件用于在 Spring IOC 容器里配置 Bean. Bean 的配置文件可以放在 classpath 下, 也可以放在其它目录下

一、IOC 和 DI

    IOC(Inversion of Control):其思想是反转资源获取的方向. 传统的资源查找方式要求组件向容器发起请求查找资源. 作为回应, 容器适时的返回资源. 而应用了 IOC 之后, 则是容器主动地将资源推送给它所管理的组件, 组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式
    DI(Dependency Injection) — IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如: setter 方法)接受来自如容器的资源注入. 相对于 IOC 而言,这种表述更直接

配置 bean
  --配置形式:基于 XML 文件的方式;基于注解的方式
  --Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean
  --IOC 容器 BeanFactory & ApplicationContext 概述
  --依赖注入的方式:属性注入;构造器注入
  --注入属性值细节
  --自动转配
  --bean 之间的关系:继承;依赖
  --bean 的作用域:singleton;prototype;WEB 环境作用域
  --使用外部属性文件
  --spEL
  --IOC 容器中 Bean 的生命周期
  --Spring 4.x 新特性:泛型依赖注入

1-1.基于 XML 文件的方式配置 bean

public class HelloWorldBean {    private String user;    public HelloWorldBean() {        System.out.println("HelloWorldBean's constructor...");    }    // 如果这里修改为setUser2,刚applicationContext.xml修改为property name="user2"    public void setUser(String user) {        System.out.println("setUser:" + user);        this.user = user;    }    public HelloWorldBean(String user) {        this.user = user;    }    public void hello(){        System.out.println("Hello: " + user);    }}
applicationContext.xml的关键内容如下:
    <!-- 通过全类名配置一个 bean,        class:bean的全类名!,是Spring通过反射的方式在IOC容器中创建Bean(对象),              所有Bean一定要有无参的构造器!!!        id:标识容器中的Bean,id是唯一的,建议用类名小写        property name:对应setter方法(public void setUser(String user)                 value:就是setter赋的值)-->    <bean id="helloWorld" class="Spring4_IOC.bean.HelloWorldBean">        <property name="user" value="Tom"/>    </bean>
id:Bean 的名称。
    在 IOC 容器中必须是唯一
    若 id 没有指定,Spring 自动将权限定性类名作为 Bean 的名字
    id 可以指定多个名字,名字之间可用逗号、分号、或空格分隔
    @Test    public void testHelloWorld() {        //        前两行可以用Spring来实现//        HelloWorldBean helloWorldBean = new HelloWorldBean();//        helloWorldBean.setUser("Tom");//        helloWorldBean.hello();        //1. 创建 Spring 的 IOC 容器(ApplicationContext代表Spring 的 IOC 容器)        //创建的时候会先调用无参构造器,同时会调用 setter方法对属性赋值!!        ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_IOC/applicationContext.xml");        System.out.println("------------------------------");        //2. 从 IOC 容器中的id获取 bean 的实例,如果为“helloWorld2”,则bean id="helloWorld2"        HelloWorldBean helloWorldBean = (HelloWorldBean) ctx.getBean("helloWorld");        //根据类型来获取 bean 的实例: 要求在  IOC 容器中只有一个与之类型匹配的 bean, 若有多个则会抛出异常.        //一般情况下, 该方法可用, 因为一般情况下, 在一个 IOC 容器中一个类型对应的 bean 也只有一个.//       HelloWorldBean helloWorld1 = ctx.getBean(HelloWorldBean.class);        //3. 使用 bean        helloWorldBean.hello();    }

HelloWorldBean's constructor...
setUser:Tom
------------------------------
Hello: Tom
1-1-1.IOC 容器

    在 Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC 容器里获取 Bean 实例并使用.
Spring 提供了两种类型的 IOC 容器实现.
  --BeanFactory: IOC 容器的基本实现.
  --ApplicationContext: 提供了更多的高级特性. 是 BeanFactory 的子接口.
  --BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory
  --无论使用何种方式, 配置文件时相同的.
ApplicationContext

  ApplicationContext 的主要实现类:
    --ClassPathXmlApplicationContext:从 类路径下加载配置文件
    --FileSystemXmlApplicationContext: 从文件系统中加载配置文件
  ConfigurableApplicationContext 扩展于 ApplicationContext,新增加两个主要方法:refresh() 和 close(), 让 ApplicationContext 具有启动、刷新和关闭上下文的能力
  ApplicationContext 在初始化上下文时就实例化所有单例的 Bean。
  WebApplicationContext 是专门为 WEB 应用而准备的,它允许从相对于 WEB 根目录的路径中完成初始化工作

1-1-2.依赖注入的方式

Spring 支持 3 种依赖注入的方式
  --属性注入
  --构造器注入
  --工厂方法注入(很少使用,不推荐)
1).属性注入
  属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象
  属性注入使用 <property> 元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 <value> 子节点指定属性值
  属性注入是实际应用中最常用的注入方式

在applicationContext.xml

    <!-- Spring 支持 3 种依赖注入的方式            属性注入(最常用)            构造器注入            工厂方法注入(很少使用,不推荐)-->    <bean id="helloWorld2" class="Spring4_IOC.bean.HelloWorldBean">        <!-- 为属性赋值 -->        <!-- 通过属性注入: 通过 setter 方法注入属性值 如setUser() -->        <property name="user" value="Tom2"/>    </bean>    <!-- 通过构造器注入属性值 -->    <bean id="helloWorld3" class="Spring4_IOC.bean.HelloWorldBean">        <!-- 要求: 在 Bean 中必须有对应的构造器.(public HelloWorldBean(String user))  -->        <constructor-arg value="Mike"/>    </bean>
2).构造方法注入
  通过构造方法注入Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化后就可以使用。
  构造器注入在 <constructor-arg> 元素里声明属性, <constructor-arg> 中没有 name 属性
public class Car {    private String company;    private String brand;    private int maxSpeed;    private float price;    public Car() {    }    public Car(String brand, float price) {        super();        this.brand = brand;        this.price = price;    }    public Car(String company, String brand, float price) {        super();        this.company = company;        this.brand = brand;        this.price = price;    }    public CarCycle(String company, String brand, int maxSpeed) {        super();        this.company = company;        this.brand = brand;        this.maxSpeed = maxSpeed;    }    public Car(String company, String brand, int maxSpeed, float price) {        super();        this.company = company;        this.brand = brand;        this.maxSpeed = maxSpeed;        this.price = price;    } //省去get,set方法    @Override    public String toString() {        return "CarCycle [company=" + company + ", brand=" + brand + ", maxSpeed="                + maxSpeed + ", price=" + price + "]";    }}

   <!-- 默认是按顺序配置的(个数),     若一个 bean 有多个构造器, 则还需要通过参数的类型来配置,如car2 -->    <!-- 可以根据 index 和 value 进行更加精确的定位. (了解) -->    <bean name="car" class="Spring4_IOC.bean.Car">        <constructor-arg value="KUGA" index="0"/>        <constructor-arg value="ChangAnFord" index="1"/>        <constructor-arg value="250000" type="float"/>    </bean>    <bean id="car2" class="Spring4_IOC.bean.Car">        <!--最好设置参数类型-->        <constructor-arg value="ChangAnMazda" type="java.lang.String"/>        <!-- 若字面值中包含特殊字符, 则可以使用 CDATA 来进行赋值. (了解) -->        <constructor-arg value="ShangHai" type="java.lang.String"/>        <!--value里的字符为<ShangHai>        <constructor-arg type="java.lang.String">            <value><![CDATA[<ShangHai>]]></value>        </constructor-arg>-->        <constructor-arg value="180" type="int"/>        <!--       上面也可以用这个代替                <constructor-arg type="int">                    <value>180</value>                </constructor-arg>-->        <!-- 测试null,没有什么意义,因为属性本来就是null。<null/>的专有标记        <constructor-arg ><null/> </constructor-arg>        -->    </bean>
    字面值:可用字符串表示的值,可以通过 <value> 元素标签或 value 属性进行注入。
    基本数据类型及其封装类、String 等类型都可以采取字面值注入的方式
   若字面值中包含特殊字符,可以使用 <![CDATA[]]> 把字面值包裹起来。
    /***********     * Bean 的配置方式:-、通过全类名(反射);二、通过工厂方法(静态工厂方法 & 实例工厂方法);三、FactoryBean     *     * 配置Bean:配置方式:通过全类名(反射)***************/    //测试依赖注入    @Test    public void testDependencyInjection() {        ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_IOC/applicationContext.xml");        Car car = (Car) ctx.getBean("car");        System.out.println("1-->"+car);        //测试car里有多个构造器,如何配置IOC        Car car2 = (Car) ctx.getBean("car2");        System.out.println("2-->"+car2);    }
1-->CarCycle [company=KUGA, brand=ChangAnFord, maxSpeed=0, price=250000.0]
2-->CarCycle [company=ChangAnMazda, brand=ShangHai, maxSpeed=180, price=0.0]
3).注入属性值细节
引用其它 Bean

    组成应用程序的 Bean 经常需要相互协作以完成应用程序的功能. 要使 Bean 能够相互访问, 就必须在 Bean 配置文件中指定对 Bean 的引用
    在 Bean 的配置文件中, 可以通过 <ref> 元素或 ref  属性为 Bean 的属性或构造器参数指定对 Bean 的引用.
    也可以在属性或构造器里包含 Bean 的声明, 这样的 Bean 称为内部 Bean
    <bean id="person" class="Spring4_IOC.bean.Person">        <property name="name" value="changwen"/>        <property name="age" value="24"/>        <!-- 可以使用property的ref 属于建立bean之间的引用关系。-->        <property name="car" ref="car2"/>        <!--    也可以这么写                <property name="car">                    <ref bean="car2"/>                </property>        -->        <!--    还能用内部bean,这个bean不能被外部引用,只能在内部使用                <property name="car">                    <bean class="Spring4_IOC.bean.CarCycle">                        <constructor-arg value="KUGA" type="java.lang.String"/>                        <constructor-arg value="ChangAnFord" type="java.lang.String"/>                        <constructor-arg value="180" type="int"/>                    </bean>                </property>        -->    </bean>

内部Bean
  --当 Bean 实例仅仅给一个特定的属性使用时, 可以将其声明为内部 Bean. 内部 Bean 声明直接包含在 <property> 或 <constructor-arg> 元素里, 不需要设置任何 id 或 name 属性
  --内部 Bean 不能使用在任何其他地方

注入参数详解:null 值和级联属性
  --可以使用专用的 <null/> 元素标签为 Bean 的字符串或其它对象类型的属性注入 null 值,意义不大
  --和 Struts、Hiberante 等框架一样,Spring 支持级联属性的配置,例如在xml文件里设置Car.price

0 0