JavaWeb: Spring框架学习1

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());
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值