• Spring入门一


    一 简介
    1.Spring为企业应用的开发提供了一个轻量级的解决方案,该解决方案包括:基于依赖注入的核心机制、基于AOP的声明式事务管理、与多种持久层技术 的整合,以及优秀的Web MVC框架等等。可以说,Spring是企业应用开发的“一站式”选择,它贯穿表现层、业务层、持久层。
    2.下载:http://projects.spring.io/spring-framework/
    当使用Spring框架时,必须使用Spring Core Container(即Spring容器),它代表了Spring框架的核心机制。Spring Core Container主要由org.framework.core、org.framework.beans、 org.framework.context、org.framework.expression四个包及其子包组成,主要由Spring IoC容器支持。
    使用Spring框架的Java Web项目,需要将Spring框架的JAR包和commons-logging-1.1.3.jar添加到Web应用的WEB-INF路径下。
    3.描述
    轻量级:Spring是非侵入性的,基于Spring开发的应用中的对象可以不依赖于Spring的API
    依赖注入(DI--dependency injection),控制反转(IOC--Inversion of Control)
    面向切面编程(AOP--aspect oriented programming)
    容器:Spring是一个容器,因为它可以包含并管理应用对象的生命周期
    框架:Spring实现了使用简单的组件配置组合成一个复杂的应用,在Spring中使用xml和java注解组合这些对象
    一站式:在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库
    二 使用Spring管理bean
    Spring核心容器的理论很简单:Spring核心容器就是一个超级大工厂,所有的对象(包括数据源、Hibernate SessionFactory等基础性)都会被当成Spring核心容器管理的对象。Spring把容器中的一切对象统称为Bean,Spring对 bean没有任何要求,只要是一个java类,Spring就可以管理该java类,并把它当做Bean处理。
    先定义一个简单的类Axe.java
    public class Axe {
         public String chop(){
              return "使用斧子砍柴";
         }
    }
    再定义一个Person类
    public class Perosn {
         private Axe axe;
         public void setAxe(Axe axe){
              this.axe=axe;
         }
         public void useAxe(){
              System.out.println("打算去砍柴点火");
              System.out.println(axe.chop());
         }
    }
    Perosn对象需要调用Axe对象的方法,这种情形成为依赖。
    Spring通过xml配置文件来管理Bean,示例:
    在项目的src下建立ApplicationContext.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:jaxws="http://cxf.apache.org/jaxws"
         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-3.2.xsd
              http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
              http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
        
         <bean id="person" class="mySpring.Person">
              <property name="axe" ref="axe"></property>
         </bean>
        
         <bean id="axe" class="mySpring.Axe" />
        
    </beans>
    配置文件中的<bean>元素默认以反射方式来调用该类无参数的构造器来创建实例,并将该实例作为Spring容器中的Bean.zai Spring配置文件中配置bean时,class属性的值必须是Bean实现类的完整类名(必须带包名),不能是接口,不能是抽象类(除非有特殊配 置),否则Spring无法使用反射创建该类的实例。
    <property>子元素会驱动Spring在底层以反射执行一次setter方法,name属性值会决定执行哪个setter方法,而 value或ref决定执行setter方法的传入参数。一旦bean被创建处理,Spring会立即根据<property>子元素执行 setter方法。也就是说,<bean>元素驱动Spring调用构造器创建对象,<property>子元素驱动 Spring执行setter方法,这两步是先后执行的,中间几乎没有任何间隔。
    访问容器中的bean:
    public class test {
         public static void main(String[] args) {
              ApplicationContext ctx=new ClassPathXmlApplicationContext("ApplicationContext.xml");
              Perosn p=ctx.getBean("person",Perosn.class);
              p.useAxe();
         }
    }
    三 Spring的核心机制--依赖注入
    1.在java应用中存在大量A对象调用B对象方法的情形,这种情形被Spring称为依赖,即A对象依赖B对象。Spring框架的核心功能有两个:
    Spring容器作为超级大工厂,负责创建、管理所有的java对象,这些java对象被称为bean。
    Spring容器通过依赖注入管理容器中Bean之间的依赖关系
    2.什么是依赖注入
    当某个java对象需要调用另一个java对象的方法时,在传统模式下通常有两种做法:
    原始做法:调用者主动创建被依赖对象,即new一个对象,再调用对象的方法。这种做法主要有两个坏处:可扩展性差,当修改了被依赖对象时,还需要修改调用者;职责不清,调用者还需要关心被依赖对象的创建过程,实际上,它只需要调用其中的某些方法即可。
    简单工厂模式:调用者找到被依赖对象的工厂,通过工厂去获取被依赖对象,调用其中的方法。这种模式要注意三点:调用者面向被依赖对象的接口编程;被依赖对象的创建交给工厂完成;调用者通过工厂来获得被依赖组件。
    使用Spring框架后,调用者只需要被动接受Spring容器为调用者的成员变量赋值即可(配置一个<property>子元 素,Spring就会执行对应的setter方法为调用者的成员变量赋值)。控制反转和依赖注入是同一个行为的两种表述,只是描述的角度不同而已。依赖注 入通常有两种方式:
    设值注入:IoC容器使用成员变量的setter方法来注入被依赖对象。
    构造注入:IoC容器使用构造器来注入被依赖对象。
    3.属性(设值)注入:
    属性注入即通过setter方法注入Bean的属性值或依赖的对象,是实际应用中最常用的注入方式
    属性注入使用<property>元素,使用name属性指定Bean的属性名称,value属性或<value>子节点指定属性值
    构造方法注入:
    通过构造方法注入Bean的属性值或依赖的对象,它保证了Bean实例在实例化后就可以使用
    构造器注入在<constructor-arg>元素里声明属性,<constructor-arg>中没有name属性
    Spring IoC容器有三个基本要点:
    (1)应用程序的各组件面向接口编程,从而可以将组件之间的耦合关系提升到接口层次,有利于后期的扩展。
    (2)应用程序的各组件不再由程序主动创建,而是由Spring容器负责产生并初始化。
    (3)Spring采用配置文件或注解来管理bean的实现类、依赖关系,Spring容器则根据配置文件或注解,利用反射来创建实例,并为之注入依赖关系。
    4.构造注入
    Car.java
    public class Car {    
         private String brand;
         private String corp;
         private double price;
         private int maxSpeed;
         public Car(String brand, String corp, double price) {
              super();
              this.brand = brand;
              this.corp = corp;
              this.price = price;
         }
         @Override
         public String toString() {
              return "Car [brand=" + brand + ", corp=" + corp + ", price=" + price
                        + ", maxSpeed=" + maxSpeed + "]";
         }
    }ApplicationContext.xml
    <!-- 通过构造方法来配置bean的属性 -->
         <bean id="car" class="a.Car">
         <constructor-arg value="Audi" index="0"></constructor-arg>
         <constructor-arg value="ShangHai" index="1"></constructor-arg>
         <constructor-arg value="300000" index="2"></constructor-arg>
         </bean>
    myTest.java:
    public class myTest {
         public static void main(String[] args) {
              ApplicationContext ctx=new ClassPathXmlApplicationContext("a/ApplicationContext.xml");
              Car car=ctx.getBean(Car.class);
              System.out.println(car);
         }
    }
    构造注入的本质是:驱动Spring在底层以反射方式执行带指定参数的构造器,当执行带参数的构造器时,就可以利用构造器参数对成员变量执行初始化。也就 是说,设值注入与构造器注入的区别在于:设值注入是先通过无参数的构造器创建一个Bean实例,然后调用对应的setter方法注入依赖关系;而构造器注 入则直接调用有参数的构造器,当Bean实例创建完成后,已经完成了依赖关系的注入。
    若在car.java中再增加如下的构造器,并希望通过该构造器来配置bean的属性:
    public Car(String brand, String corp, int maxSpeed) {
              super();
              this.brand = brand;
              this.corp = corp;
              this.maxSpeed = maxSpeed;
         }
    则相应的bean的属性为:
    <bean id="car2" class="a.Car">
         <constructor-arg value="BaoMa"></constructor-arg>
         <constructor-arg value="ShangHai"></constructor-arg>
         <constructor-arg value="240"></constructor-arg>
    </bean>
    由于有两个构造方法,相应的test.java中只能用id定位到相应的bean:
    Car car=(Car)ctx.getBean("car");
    System.out.println(car);
    Car car2=(Car)ctx.getBean("car2");
    System.out.println(car2);
    结果为:Car [brand=Audi, corp=ShangHai, price=300000.0, maxSpeed=0]
    Car [brand=BaoMa, corp=ShangHai, price=240.0, maxSpeed=0]
    此时两个构造器就会发生歧义,仅靠顺序无法解决。可以靠参数列表解决,根据参数个数和参数类型来区分
    <bean id="car2" class="a.Car">
         <constructor-arg value="BaoMa" type="java.lang.String"></constructor-arg>
         <constructor-arg value="ShangHai" type="java.lang.String"></constructor-arg>
         <constructor-arg value="240" type="int"></constructor-arg>
         </bean>
    结果为:Car [brand=Audi, corp=ShangHai, price=300000.0, maxSpeed=0]
    Car [brand=BaoMa, corp=ShangHai, price=0.0, maxSpeed=240]
    也就是说,使用构造器注入属性值可以指定参数的个数和参数的类型,来区分重载的构造器
    5.两种注入方式的对比
    设值注入的优点:
    对于复杂的依赖关系,如果采用构造注入,会导致构造器过于臃肿,难以阅读。Spring在创建Bean实例时,需要同时实例化其依赖的所有实例,从而导致性能下降,而使用设值注入则能避免这些问题。
    在某些成员变量可选的情况下,多参数的构造器更加笨重。
    构造注入的优点:
    可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入。如组件中其他依赖关系的注入常常需要依赖于Datasource的注入。
    对于依赖关系无须变化的Bean,构造注入更有用处。
    建议采用设值注入为主,构造注入为辅的注入策略。
    四 Spring容器
    1.Spring有两个核心接口:BeanFactory和ApplicationContext。其中,ApplicationContext是 BeanFactory的子接口。它们都可以代表Spring容器,Spring容器是生成Bean实例的工厂,并管理容器中的Bean。由于 ApplicationContext本身就是BeanFactory的子接口,因此ApplicationContext完全可以作为Spring容器 来使用,而且功能更强,也被称为Spring上下文。
    2.BeanFactory常用的实现类是DefaultListableBeanFactory
    ApplicationContext的常用实现类是:
    ClassPathXmlApplicationContext:从类路径下加载配置文件
    FileSystemXmlApplicationContext:从文件系统中加载配置文件
    AnnotationConfigApplicationContext
    如果是在Web应用中使用Spring容器,则通常有XmlWebApplicationContext、AnnotationConfigWebApplicationContext两个实现类。
    创建Spring容器的实例时,必须提供Spring容器管理的bean的详细配置信息,通常采用XML配置文件来设置,因此在创建ApplicationContext实例时,应该提供XML配置文件作为参数,XML配置文件通常采用Resource对象传入。
    BeanFactory接口包含以下几个基本方法:
    boolean containsBean(String name):判断Spring容器是否包含id为name的bean实例
    <T> T getBean(Class<T> requiredType):获取Spring容器中属于requiredType类型的、唯一的Bean实例
    Object getBean(String name):返回容器id为name的bean实例
    <T> T getBean(String name,Class<T> requiredType):返回容器id为name且类型为requiredType的bean实例
    Class<?> getType(String name):返回容器中id为name的Bean实例的类型
    ApplicationContext除了BeanFactory所支持的全部功能外,它还有如下额外的功能:
    (1)默认会预初始化所有的singleton Bean,也可以通过配置取消预初始化;
    (2)继承了MessageSource接口,因此可以提供国际化支持;
    (3)资源访问,比如访问URL和文件;
    (4)事件机制;
    (5)同时加载多个配置文件;
    (6)以声明式方式启动并创建Spring容器。
    当系统创建ApplicationContext容器时,默认会预初始化所有的singleton Bean。这就意味着,系统前期创建ApplicationContext时将有较大的系统开销,但一旦ApplicationContext初始化完 成,程序后面获取singleton Bean实例时将有较好的性能。
    一般情况下,对于一个普通的Bean,如果没有特殊配置,该bean就是singleton Bean,如果不想预初始化该bean,可以在<bean>元素内指定lazy-init="true"

  • 相关阅读:
    Struts2框架详解
    Eclipse利用Axis2插件构建Web Service并测试
    解决JS中各浏览器Date格式不兼容的问题
    Struts2框架下表单数据的流向以及映射关系
    JMS总结
    第一次博客园
    微信OAuth2网页授权
    将List转换成DataTable
    对文件的读写操作
    Excel文件的导出操作
  • 原文地址:https://www.cnblogs.com/lyy-2016/p/5841240.html
Copyright © 2020-2023  润新知