JavaWeb: Spring框架学习1

来源:互联网 发布:易约软件 编辑:程序博客网 时间:2024/06/05 16:10

Spring学习笔记

Spring是一个非常活跃的开源框架;它是一个基于Core来构架多层JavaEE系统的框架,它的主要目地是简化企业开发(Spring架构图)

Spring以一种非侵入式的方式来管理你的代码,Spring提倡”最少侵入”。使用框架一般要学习使用框架的api,但是Spring不需要(学习框架就是学习它的api)。

Spring的核心是IOC(反转控制)与AOP(面向切面编程)

 

Spring学习核心问题:

1)Spring容器是干么用的

2)如何帮助我们创建对象的?

3)创建对象的三种方式?

4)创建对象的两种时机?

5)哪种创建对象的时机比较好?

6)Spring如何管理对象的作用域和生命周期?

 

Spring配置文件:applicationContext.xml

SpringIOC(控制反转):把对象的创建、初始化、销毁等工作交给spring容器来做。由spring容器控制对象的生命周期(换句话说就是,让spring容器帮助我们创建对象,这样程序员就能专注于业务逻辑的实现)。

 

如何将一个类放到Spring容器里面,让它帮助我们创建对象呢?

在配置文件applicationContext.xml中对类进行配置。将类放到Spring容器里面,这个类就是bean,id是类的唯一标识,class表示全类名。把类名给Spring容器,让它帮助我们创建对象。

 

Spring帮助我们创建对象的步骤:

1)启动Spring容器。2)把对象从Spring容器中取出来。3)调用对象中的方法。

都是有模板性代码的,不需要关心对象是怎么创建的,关注于业务逻辑的处理就可以了。

 

Spring创建对象的三种方式?

1)调用默认的构造函数进行创建对象:如果写了有参数的构造函数,因为找不到无参数的函数,就会报错。

2)利用静态工厂的方式创建对象:Spring调用工厂方法创建对象,但是真正创建对象还是程序员来完成的。

3)实例工厂方法。

在Spring的配置文件中,只要是bean节点,Spring就会为该bean创建对象。

 

Spring创建对象的时机?在单例模式下(Scope)

1)默认情况下,启动Spring容器时创建对象

2)在调用getBean()方法的时候创建对象。


在spring的配置文件bean中有一个属性lazy-init="default/true/false"

a、如果lazy-init为"default/false"在启动spring容器时创建对象。

b、如果lazy-init为"true",在context.getBean时才要创建对象。

在多例的情况下,调用getBean()方法时,创建对象。

 

哪种创建对象的时机比较好?

第一种情况下,可以在启动spring容器的时候,检查spring容器配置文件的正确性,如果再结合tomcat, 如果spring容器不能正常启动,整个tomcat就不能正常启动。但是这样的缺点是把一些bean过早的放在了内存中,如果有数据,则对内存来是一个消耗(对象的生命周期变长了)。

第二种情况下,可以减少内存的消耗,但是不容易发现错误。

 

spring的bean中的scope

1、由spring产生的bean默认是单例的(可以实现数据共享)

2、可以在spring的配置文件中,scope的值进行修改="singleton/prototype"

3、如果spring的配置文件的scope为"prototype",则在得到该getBean()时才创建对象。

 

spring容器对对象生命周期的管理:

1、Spring容器创建对象

2、执行init方法

3、调用自己类的方法

4、当Spring容器关闭的时候执行destroy方法(此时对象销毁),如何关闭Spring容器呢。

 

Spring DI:依赖注入:给对象的属性赋值

1、利用set方法给属性赋值;property用来描述一个类的属性,并且对类的属性进行赋值,在bean节点下面。

1)、基本类型的的封装类,String等类型通过value进行赋值。

2)、引用类型通过ref进行赋值。

注意:一个类中的属性都可以采用SpringID的方式进行赋值,但是一般不常用,这种方式主要用于特定场合。

Spring容器会解析bean节点下的所有property对象,解析name和value,然后通过调用set方法进行赋值。


2、利用构造函数给属性赋值

SpringID的说明:如果Spring配置文件中的bean中没有<constructor-arg>元素,则调用默认的构造函数;如果Spring的配置文件中有<constructor-arg>元素,则该元素是唯一确定的构造函数。

index代表参数的位置,从0开始计算。

type表示参数的类型 java.lang.String。

value 给基本类型赋值。

ref给引用类型赋值。

 

SpringIOC和DI的意义:实现了完全的面向接口编程

 

利用springIOC和DI实现MVC的模拟例子:

把接口放到Spring容器中(配置文件中没有意义的)

SpringInit类的作用

 

Spring注解:说明(可以少写一些代码)

1)在java中注解就是为了说明某一部分的作用

2)注解都可以用于哪里是@Target注解起的作用。

3)注解可以标注在ElementType枚举类所指定的位置。

4)用来解析注解的类成为注解解析器。

<?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">    <context:component-scan base-package="main.com.tniu"/>    <!--引用另一个配置文件-->    <import resource="applicationContext_create.xml"/>    <!--在Spring容器中注册,lazy-init用于标记在在什么时候创建对象-->    <bean id="Student" class="main.com.tniu.Student" lazy-init="default"/>    <!--lazy-init懒加载,在调用getBean方法的时候创建对象-->    <bean id="Teacher" class="main.com.tniu.Teacher" lazy-init="true"/>    <!--通过静态工厂创建对象,factory-method表示调用那个工厂方法帮组我们创建对象-->    <bean id="ObjectFactory" class="main.com.tniu.ObjectFactory" factory-method="getInstance"/>    <!---->    <!--配置Scope,默认是单例模式singleton,prototype表示多例的-->    <bean id="SingleEntity" class="main.com.tniu.SingleEntity" scope="prototype"/>    <!--对象的初始化和销毁:init-method,destroy-method-->    <bean id="InitAndDestroy" class="main.com.tniu.InitAndDestroy" init-method="init" destroy-method="destory"/>    <!--通过set方法给属性赋值-->    <bean id="TestSetMethod" class="main.com.tniu.TestSetMethod">        <property name="id" value="1"/>        <property name="name" value="陈如水"/>        <property name="student" ref="Student"/>        <!--通过对list集合进行赋值-->        <property name="lists">            <list>                <value>list1</value>                <ref bean="Student"/>                <value>list2</value>            </list>        </property>        <!--对property集合进行赋值-->        <property name="prop">            <props>                <!--只能是字符串类型-->                <prop key="k1">                    test                </prop>                <prop key="k2">                    test2                </prop>            </props>        </property>        <!--对set集合进行赋值-->        <property name="sets">            <set>                <value>test</value>                <ref bean="Student"/>                <value>set1</value>            </set>        </property>        <!--对map集合进行赋值-->        <property name="map">            <map>                <entry key="key1">                    <value>v1</value>                </entry>                <entry key="key2">                    <value>v2</value>                </entry>            </map>        </property>    </bean>    <bean id="ConstructorEntity" class="main.com.tniu.ConstructorEntity">        <!--一定要和构造函数中参数的位置对应,在这里犯过错-->        <constructor-arg index="0" type="java.lang.String" value="陈如水"/>        <constructor-arg index="1" type="main.com.tniu.Student" ref="Student"/>        <constructor-arg index="2" type="java.lang.Long" value="11"/>    </bean></beans>


package main.com.tniu;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * Created by Administrator on 2017/7/11. */public class Test {    /**     * Spring帮助我们创建对象的过程     * ApplicationContext     * ClassPathXmlApplicationContext     */    @org.junit.Test    public void testSpring() {        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        Student student = (Student) context.getBean("Student");        student.sayHello();    }        /**     * 主配置文件引用另一个配置文件     */    @org.junit.Test    public void testImport() {        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        Person person = (Person) context.getBean("Person");        person.sayPerson();    }    /**     * 通过别名获取对象     */    @org.junit.Test    public void testAlias() {        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        Person person = (Person) context.getBean("alias");        person.sayPerson();    }    /**     * 容器启动的时候创建对象     */    @org.junit.Test    public void testCreateObject() {        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        System.out.println("容器启动的时候创建对象");        Student student = (Student) context.getBean("Student");        student.sayHello();        //打印顺序:通过构造方法创建对象--->容器启动的时候创建对象    }    /**     * 调用getBean()的时候创建对象     */    @org.junit.Test    public void testCreateObjectTwo() {        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        System.out.println("getBean创建对象");        Teacher teacher = (Teacher) context.getBean("Teacher");        teacher.sayHello();    }    /**     * 创建对象的方式,Spring容器通过调用构造方法获取对象     * 通过静态工厂创建对象     * 需要把静态工厂类加入到配置文件当中     */    @org.junit.Test    public void createMethod() {        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        //直接转化成Student类        Student student = (Student) context.getBean("ObjectFactory");        student.sayHello();    }    /**     * Spring帮助我们创建的对象是不是单例的?     * 如果是单例的,就存在数据共享(对象中的成员变量和成员方法)     * 两个对象的内存地址值是一样的,说明是单例的;     * 如何去验证数据共享呢     * 如果修改bena中的Scope属性为prototype,则变成多例的,地址值是不一样的     * 注意:如果设置Scope属性为prototype,则对象是在调用getBean()方法的时候创建,在使用Struct2的时候     * action的创建必须是多例的,并且需要在容器启动的时候创建,所以要用到scope属性。     */    @org.junit.Test    public void testSingle() {        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        Student student = (Student) context.getBean("Student");        System.out.println(student);        student.getList().add("a");        Student student1 = (Student) context.getBean("Student");        student1.getList().add("b");        System.out.println(student1);        //打印集合的长度,结果为2        System.out.println(student1.getList().size());    }    /**     * 初始化方法和销毁方法的调用     * 对象的生命周期     * 如何关闭Spring容器 close()方法     */    @org.junit.Test    public void testInitAndDestroy() {        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        InitAndDestroy initAndDestroy = (InitAndDestroy) context.getBean("InitAndDestroy");        //打印结果:构造方法--->init方法        ClassPathXmlApplicationContext app = (ClassPathXmlApplicationContext) context;        app.close();    }    /**     * 通过set方法给类的属性赋值     * 没有能打印出结果     */    @org.junit.Test    public void testSetMethod() {        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        TestSetMethod testSetMethod = (TestSetMethod) context.getBean("TestSetMethod");        testSetMethod.toString();    }    /**     * 通过构造函数进行赋值     * 可以进行正常的打印     */    @org.junit.Test    public void testSetMethodCon() {        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        ConstructorEntity con = (ConstructorEntity) context.getBean("ConstructorEntity");        System.out.println(con.getName());        System.out.println(con.getStudent());        System.out.println(con.getId());    }}