关于Spring你所需要知道的一切(第一天)

重视java编程思想去学习spring框架。Spring轻量级容器。作用于整个三层架构(struts2作用于web.hibrenate作用于dao层是重量级)

struts2作用于web层。hibernate作用于刀层。spring作用于整个三层架构。

三层架构;

  • IOC 控制反转(依赖注入)
  • AOP 面向切面编程 事务

搭建Spring环境

所需要的资源Spring.这里是我们所需要的整个资源。我们一般开发中只需其中的某些包就可以,所以我们一般导入自己需要的包,在这里我将常用的包能解决一般开发问题所需要的包提取在jar文件中。这里我们导入jar下面的所有包。为了在写配置文件中有代码提示,我们还需要导入两个.xsd文件。在schema目录下。我们将这两个东西也导入到项目中,在xml catalog中进行关联,注意关联的时候Key type选择URI,KEY值我们是在配置文件中寻找那两个KEY。如:http://www.springframework.org/schema/beans

  • 将上面步骤整理好后,我们先新建一个包在新建一个类Student。给定相应的属性后,我们还需要添加get/set方法。给出了有参构造函数,必须在添加无参构造函数。

  • 在写一个配置文件。文件可以起任意名字。bean.xml;

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

这个文件的头部声明可以在下载的spring文档中的示例找到.注意这里面用到了俩个schema文件(.xsd文件),就是spring-beans-3.2.xsd和spring-context-3.2.xsd,这俩个文件在下载的spring文档中也是可以找到的.我们在Eclipse中把xml文件和schema文件关联(注意上课的演示步骤)后,在这个xml中就可以有智能提示了。还有一点需要注意,将来我们这xml中再引入另外的schema文件后在配置的时候就可以智能提示出新的配置内容,spring是又很多模块组成的,我们需要什么功能的配置标签就需要引入对应的schema文件,从而获得智能提示,同时也能帮我们验证配置的正确性

  • 在这里我们在<bean>添加子标签配置bean类。

      <bean name="student" class="com.zts.ioctest.Student" scope="prototype">
      <!--这里的name属性的值就是,setName,去掉set,首字母小写 -->
      <property name="name" value="tom">
      </property>
      </bean>
    
  • 测试(我们在Main方法中测试)

       //beanfactory 功能简陋一般不用
      //所以我们一般拿 ApplicationContext
      ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
      Student bean = (Student) ac.getBean("student");
        String name = bean.getName();
        System.out.println(name);
        System.out.println(bean);
    

Spring详细分析

软件应用分层架构

标准三层架构:

  • 数据访问层:主要是对原始数据(数据库或者文本文件等存放数据的形式)的操作层,而不是指原始数据,也就是说,是对数据的操作,而不是数据库,具体为业务逻辑层或表示层提供数据服务.
  • 业务逻辑层:主要是针对具体的问题的操作,也可以理解成对数据层的操作,对数据业务逻辑处理,如果说数据层是积木,那逻辑层就是对这些积木的搭建。具体的讲主要负责对数据层的操作。也就是说把一些数据层的操作进行组合。
  • 表示层:主要表示WEB方式,如果逻辑层相当强大和完善,无论表现层如何定义和更改,逻辑层都能完善地提供服务。主要对用户的请求接受,以及数据的返回,为客户端提供应用程序的访问。

优点:

  1. 开发人员可以只关注整个结构中的其中某一层;
  2. 可以很容易的用新的实现来替换原有层次的实现;
  3. 可以降低层与层之间的依赖;
  4. 有利于标准化;
  5. 利于各层逻辑的复用。
  6. 结构更加的明确
  7. 在后期维护的时候,极大地降低了维护成本和维护时间

缺点:

  1. :降低了系统的性能。这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成。
  2. 有时会导致级联的修改。这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码。
  3. 增加了开发成本。

IOC注入

set方式注入(必须依靠set方法)

可以注入的内容有:

  1. 基本类型(8中基本类型+字符串)的装配
  2. 对象类型的装配
  3. 集合的装配
基本类型的装配

方式: 配置元素<value/>

例子:

public class HelloBean {
    private String name;
    private int age;
    public String sayHello(){
        return "hello "+name +",your age is" + age;
    }
    .............
}

配置文件set.xml

<bean id="helloBean" class="ioc.HelloBean">
    <property name="name">
        <value>tom</value>
    </property>
        <property name="age" value="20">
    </property>
</bean>
<!--
id是Bean的唯一标识,要求在整个配置文件中要唯一,也可使用name属性,bean标签里面的id和name属性都可以用来标识这个配置的对象,但是id会帮我们检查给对象起的名字是否规范(名字不能重复、不能用数字开头、不能有空格等等),如果检查出来了那么就会报错。name属性不会帮检查这些东西。
 -->
<!--property 对于所有用set方式来注入的必须改标签-->
<!--value    是对以基本类型,都用value(标签/属性)来注入,可以实现自动的数据类型转换-->

测试类:

   main:
    ApplicationContext ac = 
        new ClassPathXmlApplicationContext("set.xml");
    //获取容器的一个实例
    HelloBean hb = (HelloBean) ac.getBean("helloBean");
    System.out.println(hb.sayHello());
对象类型的装配
  1. <ref local=" "/> 用于涉及的对象的id在当前配置文件中(用于在本配置文件中配置了的bean的引入同ref="..")

  2. <ref bean=" "/> 用于涉及的对象的id不在本配置文件中
    (用于引用不在本配置文件中配置的bean)

  3. 使用property的ref属性引用

     public class OtherBean {
     private String str1;
     public String getStr1() {
         return str1;
     }
     public void setStr1(String str1) {
         this.str1 = str1;
     }
     public String toString(){
         return "OtherBean "+str1;
     }
      }
    
      public class SomeBean {
     private OtherBean ob;
     public void printInfo(){
         System.out.println("someBean "+ob);
     }
     public OtherBean getOb() {
         return ob;
     }
     public void setOb(OtherBean ob) {
         this.ob = ob;
     }
     }
    

配置applicationContext.xml

    <bean id="someBean" class="ioc.SomeBean">
    <property name="ob">
        <ref bean="otherBean" />
    </property>
    </bean>

配置other.xml文件

    <bean id="otherBean" class="ioc.OtherBean">
    <property name="str1">
        <value>string1</value>
    </property>
    </bean>

测试类:
main:
String[] path = {"ioc/applicationContext.xml","ioc/other.xml"};
ApplicationContext ac = new ClassPathXmlApplicationContext(path);
SomeBean sb = (SomeBean) ac.getBean("someBean");
sb.printInfo();

集合的装配

方式:配置元素<list> <set> <map> <props>

    public class SomeBean {
    private List listProperty;
    private Set setProperty;
    private Map mapProperty;
    private Properties<String,String> property;
    public List getListProperty() {
        return listProperty;
    }
    public void setListProperty(List listProperty) {
        this.listProperty = listProperty;
    }
    public Set getSetProperty() {
        return setProperty;
    }
    public void setSetProperty(Set setProperty) {
        this.setProperty = setProperty;
    }
    public Map getMapProperty() {
        return mapProperty;
    }
    public void setMapProperty(Map mapProperty) {
        this.mapProperty = mapProperty;
    }
    public Properties getProperty() {
        return property;
    }
    public void setProperty(Properties property) {
        this.property = property;
    }
    public void printInfo(){
        System.out.println("listProperty");
        System.out.println(listProperty);
        System.out.println("setProperty");
        System.out.println(setProperty);
        Set set = mapProperty.entrySet();
        Iterator it = set.iterator();
        while(it.hasNext()){
             Map.Entry entry = (Entry) it.next();
             System.out.println("Key " +entry.getKey() );
             System.out.println("value "+entry.getValue());
        }
        System.out.println("props: ");
        Set set2 = property.entrySet();
        Iterator it2 = set2.iterator();
        while(it2.hasNext()){
            Map.Entry entry= (Entry) it2.next();
            System.out.println("key "+entry.getKey());
            System.out.println("value "+entry.getValue());
        }
    }
}

applcationContext.xml的写法:

    <bean id="someBean" class="ioc.SomeBean">
    <property name="listProperty">
         <list>
            <value>list1</value>
            <value>list1</value>
            <value>list3</value>
         </list>
    </property>
    <property name="setProperty">
         <set>
            <value>set1</value>
            <value>set1</value>
            <value>set3</value>
         </set>
    </property>
    <property name="mapProperty">
         <map>
            <entry key="key1">
              <value>value1</value>
            </entry>
            <entry key="key2">
              <value>value2</value>
            </entry>
         </map>
    </property>
    <property name="property">
         <props>
          <prop key="key1">prop1</prop>
          <prop key="key2">prop2</prop>
          <prop key="key3">prop3</prop>
         </props>
    </property>
</bean>

测试类:

    main:
    String path = "ioc/applicationContext.xml";
    ApplicationContext  ac =
        new ClassPathXmlApplicationContext(path);
    SomeBean sb = (SomeBean) ac.getBean("someBean");
    sb.printInfo();
基于构造器注入

方式: 配置<constructor-arg>元素
在Bean中不用写set方法,但是要有相应的构造器

构造器注入有俩种形式 一个是根据参数类型 一个是根据参数位置的下标

    <constructor-arg type="int" value="">
    <constructor-arg  index="0" value="">

例如:

     <bean name="student" class="com.briup.bean.Student">
        <constructor-arg type="int" value="25">
        </constructor-arg>
        
        <constructor-arg type="java.lang.String" value="tom">
        </constructor-arg>
        
        <constructor-arg type="long" value="100">
        </constructor-arg>
     
</bean>

或者:
<bean name="student" class="com.briup.bean.Student">
     <constructor-arg index="2">
        <value>30</value>
     </constructor-arg>
     
     <constructor-arg index="0">
        <value>200</value>
     </constructor-arg>
     
     <constructor-arg index="1">
        <value>lily</value>
     </constructor-arg>
</bean>
自动注入 :容器依照一些规则去装配bean中的一个属性

注意:自动装配只对[对象类型]起作用,对基本类型不起作用.

第一种情况:
在beans标签中配置装载方式:default-autowire="byName"
default-autowire="byName"
在根元素beans中加入这个属性,那么下面所有的bean都会
使用byName的方式进行自动注入,如果在下面的某一个bean
里面想使用其他的方式进行注入,可以用autowire=""属性进行
说明,或者某一个bean不想使用任何自动注入就使用autowire="no"

第二种情况:

  1. 在bean标签中指定配置方式

    1. autowire="byName":
      spring容器会到当前的类中找property的名字,然后
      再根据这个名字去spring容器中找有没有和这个property
      名字相同的对象,有的话,就把这个对象当做参数放到
      setXxxx这个方法里面注入进来.
      注意:了解property指的类中的什么东西。

    2. autowire="byType":
      spring容器会根据当前类中的set方法里面参数的类型,
      去容器中找相匹配的对象,如果没找到就算了,如果找到
      一个就注入进来,如果找到多个,那么就会报错了.

    autoWrite="constructor"
    根据构造器的参数类型去匹配

继承:并不是oo的继承关系

bean的定义的继承,指bean的配置可去继承

              true 抽象化 代码中不能getBean获取其对象
  abstract =  
              false 默认

  parent = "父类bean的id/name"

  例子:
<bean name="student" class="com.briup.bean.Student">
    <property name="name">
        <value>zhangsan</value>
    </property>
</bean>

<!-- 
    abstract="true" 表示当前的配置是一个抽象的配置,
    这时候我们在代码中就不能通过这个bean的名字teacher来
    获得相应的对象了(和java中的抽象类不能直接new对象的道理一样)
    
    但是我们可以在写一个配置去继承这个抽象的配置,当然即使当前
    这个配置不是抽象的,也能够被继承(和java中继承一样)
-->

<bean name="teacher" class="com.briup.bean.Teacher" abstract="true">
    <property name="student" ref="student"></property>
</bean>

<!-- 
    parent="teacher" 表示当前配置是继承了另外一个名字叫
    teacher的bean的配置,配置和配置的继承像java中的类和类
    直接的继承一样,子类会把父类中的对象继承过来.
    当然在子配置里面依然是可以覆盖父配置中已经写的配置信息.
-->

<bean name="t" parent="teacher">

    <property name="id">
        <value>11</value>
    </property>

    <property name="name">
        <value>TeacherWang</value>
    </property>
</bean>

bean对象的生命周期

生命周期执行的过程如下:

  1. spring对bean进行实例化,默认bean是单例
  2. 2)spring对bean进行依赖注入
  3. 3)如果bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法
  4. 如果bean实现了BeanFactoryAware接口,spring将调用setBeanFactory方法,将BeanFactory实例传进来
  5. 如果bean实现了ApplicationContextAware()接口,spring将调用setApplicationContext()方法将应用上下文的引用传入
  6. 如果bean实现了BeanPostProcessor接口,spring将调用它们的postProcessBeforeInitialization接口方法
  7. 如果bean实现了InitializingBean接口,spring将调用它们的afterPropertiesSet接口方法,类似的如果bean使用了init-method属性声明了初始化方法,改方法也会被调用
  8. 如果bean实现了BeanPostProcessor接口,spring将调用它们的postProcessAfterInitialization接口方法
  9. 此时bean已经准备就绪,可以被应用程序使用了,他们将一直驻留在应用上下文中,直到该应用上下文被销毁
  10. 若bean实现了DisposableBean接口,spring将调用它的distroy()接口方法。同样的,如果bean使用了destroy-method属性声明了销毁方法,则该方法被调用

其实很多时候我们并不会真的去实现上面说描述的那些接口,那么下面我们就除去那些接口针对bean的单例和非单例来描述下bean的生命周期:

  1. 单例管理的对象:

    1. 默认情况下,spring在读取xml文件的时候,就会创建对象。
    2. 在创建的对象的时候(先调用构造器),会去调用init-method=".."
      属性值中所指定的方法.
    3. 对象在被销毁的时候,会调用destroy-method="..."属性值中
      所指定的方法.(例如调用container.destroy()方法的时候)
    4. lazy-init="true",可以让这个对象在第一次被访问的时候创建
  2. 非单例管理的对象:

    1. spring读取xml文件的时候,不会创建对象.
    2. 在每一次访问这个对象的时候,spring容器都会创建这个对象,并且
      调用init-method=".."属性值中所指定的方法.
    3. 对象销毁的时候,spring容器不会帮我们调用任何方法,
      因为是非单例,这个类型的对象有很多个,spring容器一旦把
      这个对象交给你之后,就不再管理这个对象了.

Spring框架的学习第二天
Spring框架的学习第二天

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容