美文网首页
Spring之初体验

Spring之初体验

作者: 紫荆秋雪_文 | 来源:发表于2019-09-29 00:06 被阅读0次

    一、IoC和DI

    1、IoC:Inverse of Control(控制反转):读作“反转控制”,更好理解,不是什么技术,而是一种设计思想,好比于MVC。就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。

    • 正控:若调用者需要使用某个对象,其自身就得负责该对象的创建。

    • 反控:调用者只管负责从Spring容器中获取需要使用的对象,不关心对象的创建过程,也就是把创建对象的控制权反转给了Spring框架。

    2、DI:Dependency Injection(依赖注入)

    从字面上分析:

    • IoC:指将对象的创建权,反转给了Spring容器;

    • DI :指Spring创建对象的过程中,将对象依赖属性(简单值,集合,对象)通过配置设值给该对象。

    IoC和DI其实是同一个概念的不同角度描述,DI相对IoC而言,明确描述了“被注入对象依赖IoC容器配置依赖对象”。

    3、Container:容器

    在生活中容器就是一种盛放东西的器皿,从程序设计角度看作是装对象的对象,因为存在对对象的存入、取出等操作,所以容器还要管理对象的生命周期。

    二、Spring初体验

    1、依赖jar包

    • spring-beans-5.1.0.RELEASE.jar
    • spring-core-5.1.0.RELEASE.jar
    • commons-logging-1.2.jar(spring依赖包)

    2、创建applicationContext.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"
           xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!-- 把对象的创建权交给Spring
             id:给当前<bean/>起唯一的标识名称,也作为创建对象的名称、
             class:需要交给 Spring 管理类的权限定名
         -->
        <bean id="hello" class="com.revanwang.ioc.HelloWorld">
            <!--给bean注入值-->
            <property name="username" value="Revan"/>
        </bean>
    
    </beans>
    

    3、HelloWorld

    package com.revanwang.ioc;
    
    import lombok.Setter;
    
    public class HelloWorld {
    
        @Setter
        private String username;
    
        public void sayHello() {
            System.out.println("你好,Spring " + this.username);
        }
    }
    

    4、从容器中获取bean对象

        public void testIoC() {
            //1、从classpath根路径加载资源文件,创建资源对象
            Resource resource = new ClassPathResource("applicationContext.xml");
            //2、创建Spring对象
            BeanFactory factory = new XmlBeanFactory(resource);
            //3、从Spring容器中获取指定id名称的对象
            HelloWorld world = (HelloWorld) factory.getBean("hello");
            world.sayHello();
        }
    

    三、Spring原理

    1、BeanFactoory

    Spring最基本的接口,表示Spring容器:生产bean对象的工厂,负责配置,创建和管理bean。

    • bean是Spring管理的单位,在Spring中一切都是bean

    2、Spring管理bean的原理

    • 1、通过Resource对象加载配置文件
    • 2、解析配置文件(applicationContext.xml),得到指定名称的bean
    • 3、解析bean元素,id作为bean的名称,用来从Spring获取bean对象的标识,class用于反射得到bean的实例
        Class clz = Class.forName("com.revanwang.ioc.HelloWorld");
        Constructor con = clz.getDeclaredConstructor();
        con.setAccessible(true);
        HelloWorld obj = (HelloWorld)con.newInstance();
        //--------------------------------------
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor pd : pds) {
            if("name".equals(pd.getName())){
                Method setterMethod =pd.getWriteMethod();
                setterMethod.invoke(obj, "Revan");
                break;
            }
        }
        obj.sayHello();
    
    • 4、调用getBean方法的时候,从容器中返回对象实例

    注意:

    1、这种配置下,所有的bean保证有一个无参数构造器(和访问权限无关)

    2、把代码从Java文件中 转移 到了XML中

    3、getBean方法的三种签名

    方法一:按照类型拿bean

    注意:要求在Spring中只能配置一个这种类型的实例,否则报错

        @Test
        public void testIoC() {
            //1、从classpath根路径加载资源文件,创建资源对象
            Resource resource = new ClassPathResource("applicationContext.xml");
            //2、创建Spring对象
            BeanFactory factory = new XmlBeanFactory(resource);
            //3、从Spring容器中获取指定id名称的对象
    //        HelloWorld world = (HelloWorld) factory.getBean("hello");
            //按照类型拿bean
            HelloWorld world = factory.getBean(HelloWorld.class);
            world.sayHello();
        }
    

    方法二:按照bean的名字拿bean

    注意:按照名字拿bean不是太安全

        @Test
        public void testIoC() {
            //1、从classpath根路径加载资源文件,创建资源对象
            Resource resource = new ClassPathResource("applicationContext.xml");
            //2、创建Spring对象
            BeanFactory factory = new XmlBeanFactory(resource);
            //3、从Spring容器中获取指定id名称的对象
            HelloWorld world = (HelloWorld) factory.getBean("hello");
            //按照类型拿bean
            //HelloWorld world = factory.getBean(HelloWorld.class);
            world.sayHello();
        }
    

    方法三:按照bean的名字和类型拿bean(推荐使用)

        @Test
        public void testIoC() {
            //1、从classpath根路径加载资源文件,创建资源对象
            Resource resource = new ClassPathResource("applicationContext.xml");
            //2、创建Spring对象
            BeanFactory factory = new XmlBeanFactory(resource);
            //3、从Spring容器中获取指定id名称的对象
            //HelloWorld world = (HelloWorld) factory.getBean("hello");
            //按照类型拿bean
            //HelloWorld world = factory.getBean(HelloWorld.class);
            HelloWorld world = factory.getBean("hello", HelloWorld.class);
            world.sayHello();
        }
    

    四、Spring的基本配置

    4.1:在Spring配置中,id和name属性都可以定义bean元素的名称,不同的是:

    • id属性,遵守XML语法的ID约束(唯一)。必须以字母开始,可以使用字母、数字、连字符、下划线、句话、冒号,不能以“/”开头。
    • name属性,就可以使用很多特殊字符,比如在Spring和Struts1或Spring MVC的整合中,就得使用name属性来的定义bean的名称。
    <bean id="hello" class="com.revanwang.ioc.HelloWorld">
            <!--给bean注入值-->
            <property name="username" value="Revan"/>
    </bean>
    

    注意:从Spring3.1开始,id属性不再是ID类型了,而是String类型,也就是说id属性也可以使用“/”开头了,而bean元素的id的唯一性由容器负责检查。当然也使用name属性为<bean/>元素起多个别名,多个别名之间使用逗号或空格隔开,在代码中依然使用BeanFactory对象.getBean(...)方法获取。

    <bean id="hello, h" class="com.revanwang.ioc.HelloWorld"/>
    OR
    <bean id="hello h" class="com.revanwang.ioc.HelloWorld"/>
    

    建议:bean起名尽量规范,不要搞一些非主流的名字,尽量使用id。

    4.2:Spring中引入其他配置文件

    在实际开发中,随着应用规模的增加,系统中<bean>元素配置的数量也会大量增加,导致applicationContext.xml配置文件变得非常臃肿。为了避免applicationContext.xml文件过于庞大、臃肿,为提高其可读性,我们可以将一个applicationContext.xml文件分解成多个配置文件,然后在applicationContext.xml文件中包含其他配置文件即可。
    使用import元素引入其他的配置文件:

    <import resource="classpath:com/revanwang/ioc/hello.xml"/>
    

    使用import元素注意:
    1、默认情况下,从classpath的跟路径寻找。
    2、可以使用前缀来定位文件的基础位置:
    ①:[classpath:]:后面的文件从classpath路径开始找(推荐);[注意classloader的问题。]
    ②:[file:]:后面的文件使用文件系统的路径开始找;

    注意:只有当框架中实现了Resource接口才能够识别上述的前缀标识符。

    五、Spring测试

    5.1、传统的测试

    传统的测试存在问题:

    • 1,每个测试都要重新启动Spring容器,启动容器的开销大,测试效率低下。
    • 2,不应该是测试代码管理Spring容器,应该是Spring容器在管理测试代码。

    5.2、Spring测试

    jar包

    • junit-4.12.jar
    • spring-test-5.1.0.RELEASE.jar
    • spring-context-5.1.0.RELEASE.jar
    • spring-expression-5.1.0.RELEASE.jar
    • spring-aop-5.1.0.RELEASE.jar

    ContextConfiguration

    • @ContextConfiguration("classpath:applicationContext.xml")
    • ContextConfiguration:默认去找的当前测试类名-context.xml配置文件,如:HelloWorldTest-context.xml
    package com.revanwang.ioc;
    
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    
    //告诉JVM,Spring容器直接运行在JVM中
    @RunWith(SpringJUnit4ClassRunner.class)
    //加载配置文件
    @ContextConfiguration("classpath:applicationContext.xml")
    public class SpringTest {
    
        @Autowired
        private BeanFactory factory;
    
        @Test
        public void test1() {
            HelloWorld helloWorld = factory.getBean("hello", HelloWorld.class);
            helloWorld.sayHello();
        }
    }
    
    SpringTest.png

    相关文章

      网友评论

          本文标题:Spring之初体验

          本文链接:https://www.haomeiwen.com/subject/ykbyuctx.html