1-Spring核心概念-IOC

目录

一、Spring的作用

二、Spring-IOC思想

1、IOC-控制反转

2、DI-依赖注入

3、IOC使用

4、bean标签和属性

三、Spring创建对象的四种方式

1、无参构造函数  

2、有参数构造函数

3、静态工厂模式

4、非静态工厂

四、依赖注入的四种方式

1、set方法注入

2、构造函数注入

3、p名称空间注入

4、spel注入


Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。

Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架

Spring是一个非常活跃的开源框架,基于IOC和AOP来构架多层JavaEE系统,以帮助分离项目组件之间的依赖关系。它的主要目地是简化企业开发

一、Spring的作用

  • IOC思想  方便解耦,简化开发:Spring 就是一个大工厂,可以将所有对象创建和依赖关系维护,交给 Spring容器管理!
  • AOP 编程(面向切面编程)的支持:Spring 提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能!
  • 声明式事务的支持:只需要通过配置就可以完成对事务的管理,而无需手动编程 SSM  SSS  SSH
  • 方便程序的测试:Spring 对 Junit4 支持,可以通过注解方便的测试 Spring 程序,Spring-test :Spring的测试模块!
  • 方便集成各种优秀框架:Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts2、Hibernate、MyBatis、Quartz(定时任务)等)的直接支持,Spring框架可以无缝整合其他的框架:MyBatis、Hibernate、Redis、Activiti、SpringMVC、SpringDATA...
  • 降低 JavaEE API 的使用难度:Spring对 JavaEE 开发中非常难用的API(JDBC、JavaMail、远程调用等),都提供了封装,使这些 API 应用难度大大降低

二、Spring-IOC思想

依赖注入或控制反转的定义中,调用者不负责被调用者的实例创建工作,该工作由Spring框架中的容器来负责,它通过开发者的配置来判断实例类型,创建后再注入调用者。

由于Spring容器负责被调用者实例,实例创建后又负责将该实例注入调用者,因此称为依赖注入

而被调用者的实例创建工作不再由调用者来创建而是由Spring来创建,控制权由应用代码转移到了外部容器,控制权发生了反转,因此称为控制反转。

1、IOC-控制反转

IOC-Inversion of Control,即控制反转。它不是什么技术,而是一种设计思想

传统的创建对象的方法是直接通过 new 关键字,而 spring 则是通过 IOC 容器来创建对象,也就是说我们将创建对象的控制权交给了 IOC 容器。

我们可以用一句话来概括 IOC:

IOC 让程序员不在关注怎么去创建对象,而是关注与对象创建之后的操作,把对象的创建、初始化、销毁等工作交给spring容器来做。

IOC概念:程序中开发者不需要人工的创建对象,而是把创建的对象权利或者工作转交给Spring容器(IOC容器),让Spring容器去创建并管理这些对象,以达到程序的高度解耦的目的!

2、DI-依赖注入

Dependency Injection,说的是创建对象实例时,同时为这个对象注入它所依赖的属性。相当于把每个bean与bean之间的关系交给容器管理。而这个容器就是spring。

例如我们通常在 Service 层注入它所依赖的 Dao 层的实例;在 Controller层注入 Service层的实例。

DI  给对象属性赋值的过程叫做依赖注入

3、IOC使用

pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>testspring</groupId>
    <artifactId>testspring</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>

        <!--单元测试包-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

创建一个javaBean类

public class Person {
    private String name;
    private int age;
    // 构造方法 + GetterAndSetter + toString
}

创建配置文件

建议命名: 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">

    <!-- id 和 name 可以同时存在,作为bean的标识 class添加的应该是class的全路径 -->
    <bean id="person1" name="person1" class="bean.Person" scope="singleton" lazy-init="true">
        <!--属性通过set方法赋值-->
        <property name="name" value="merry"/>
        <property name="age" value="18"/>
    </bean>

</beans>

测试用例

public class TestSpring {
    @Test
    public void test1() {
        // 启动加载配置文件,并启动Spring框架
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取配置文件中的对象
        Person person = applicationContext.getBean("person1", Person.class);
        System.out.println(person);
    }
}

4、bean标签和属性

bean标签bean标签,是根标签beans内部必须包含的标签,它是用于声明具体的类的对象!

name属性:name不能重复!name之间可以指定多个逗号隔开!可以使用特殊字符,也可以根据name属性获取一个对象!

id属性:id属性作用和name几乎相同,但是也有细微的差别,id不可重复,且不能使用特殊字符

<!-- id 和 name 可以同时存在,作为bean的标识 class添加的应该是class的全路径 -->
<bean id="person1" name="personName1,personName2,personName3" class="bean.Person" />

通过java代码获取

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Person personId = applicationContext.getBean("personId", Person.class);
Person personName1 = applicationContext.getBean("personName1", Person.class);
Person personName2 = applicationContext.getBean("personName2", Person.class);
Person personName3 = applicationContext.getBean("personName3", Person.class);

scope属性(作用域):bean标签中添加scope属性,设置bean对应对象生成规则。

scope = "singleton" 默认值,Spring容器默认创建的对象是单例!单例,默认值,适用于实际开发中的绝大部分情况。

scope="prototype" ,创建的对象是多例(每次使用对象的时候额外创建一个新的)多例,适用于Struts2、SpringMvc中的action配置

lazy-init属性

注意: 只对单例有效,设置scope="singleton"时测试延时创建属性.

lazy-init="default" 默认值,不延迟创建,即在框架启动时候就立即创建对象。

lazy-init="false" 默认值,不延迟创建,即在框架启动时候就立即创建对象。

lazy-init="true" 延迟初始化,在用到对象的时候才会创建对象。

三、Spring创建对象的四种方式

Spring的核心思想四IOC,即所有对象的创建都是通过Spring,而不需要自己手动生成。Spring创建对象有以下几种方式:

  • 无参构造器
  • 有参构造器
  • 工厂模式:静态方法 + 非静态方法

1、无参构造函数  

默认调用无参数,之前使用的方式调用了类的无参构造函数

applicationContext.xml配置

<!-- 方式1:调用的是无参数的构造方法 -->
    <bean id="person1" name="person1" class="bean.Person" scope="singleton" lazy-init="true">
        <!--属性通过set方法赋值-->
        <property name="name" value="merry"/>
        <property name="age" value="18"/>
    </bean>

2、有参数构造函数

applicationContext.xml配置

<!--方式2:调用用有参数的构造方法-->
    <bean id="person2" class="bean.Person">
        <constructor-arg index="0" type="java.lang.String" value="Bob"/>
        <constructor-arg index="1" type="int" value="18"/>
    </bean>

在调用有参数的构造方法的时候,推荐 name和index 一起用 或者 type和index一起用,以防歧义问题!

3、静态工厂模式

创建工厂类:

public class PersonFactory {
    public static Person createPerson(){
        return new Person("jack",18);
    }
}

applicationContext.xml配置

<!--方式3:使用一个静态工厂创建对象-->
    <bean id="person3" class="factory.PersonFactory" factory-method="createPerson"/>

4、非静态工厂

创建工厂类

public class NoStaticPersonFactory {
    public Person createPerson(){
        return new Person("Tom",20);
    }
}

applicationContext.xml配置

<!--方式3:使用非静态工厂-->
    <bean id="factory" class="factory.NoStaticPersonFactory"/>
    <bean id="person4" factory-bean="factory" factory-method="createPerson"/>

测试:

public class TestSpring {
    @Test
    public void test1() {
        // 启动加载配置文件,并启动Spring框架
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取配置文件中的对象
        Person person1 = applicationContext.getBean("person1", Person.class);
        System.out.println(person1);
        Person person2 = applicationContext.getBean("person2", Person.class);
        System.out.println(person2);
        Person person3 = applicationContext.getBean("person3", Person.class);
        System.out.println(person3);
        Person person4 = applicationContext.getBean("person4", Person.class);
        System.out.println(person4);
    }
}

测试结果:

四、依赖注入的四种方式

1、set方法注入

默认是调用属性的setXXX()方法赋值!

<bean id="person1" name="person1" class="bean.Person" scope="singleton" lazy-init="true">
        <!--属性通过set方法赋值-->
        <property name="name" value="merry"/>
        <property name="age" value="18"/>
    </bean>

引入类型值注入——使用ref

创建Car对象

public class Car {
    private String name;
    private String color;
    // getterAndSetter + 构造器 + toString
}

修改Person.java,在Person中引入Car

public class Person {
    private String name;
    private int age;
    private Car car;
    // getterAndSetter + 构造器 + toString
}

配置:利用ref属性给 person的car属性赋值

<bean id="person1" name="person1" class="bean.Person" scope="singleton" lazy-init="true">
        <!--属性通过set方法赋值-->
        <property name="name" value="merry"/>
        <property name="age" value="18"/>
        <property name="car" ref="car"/>
    </bean>

    <bean id="car" name="car" class="bean.Car">
        <!--属性通过set方法赋值-->
        <property name="name" value="MINI"/>
        <property name="color" value="red"/>
    </bean>

执行结果:

2、构造函数注入

在Person中创建有参构造函数:

public class Person {

    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // GetterAndSetter + toString
}

applicationContext.xml配置

<bean id="person2" class="bean.Person">
        <constructor-arg index="0" type="java.lang.String" value="Bob"/>
        <constructor-arg index="1" type="int" value="18"/>
    </bean>

index属性:按参数索引注入,参数名一致,但位置不一致时,使用 index;同时使用 index 也可以确定调用哪个构造函数

type属性:按参数类型注入,参数名和位置一致,但类型不一致时,使用type

3、p名称空间注入

导入p名称空间:

使用p:属性名 完成注入,走set方法

  • - 基本类型值:  p:属性名="值"
  • - 引入类型值:  P:属性名-ref="bean名称"

applicationContext.xml配置

<bean id="person1" name="person1" class="bean.Person" p:name="merry" p:age="18"/>

4、spel注入

spring Expression Language:spring表达式语言

applicationContext.xml配置

<!--person1-->
    <bean id="person1" name="person1" class="bean.Person" p:name="merry" p:age="18"/>
    <!--person2-->
    <bean id="person2" class="bean.Person">
        <constructor-arg index="0" type="java.lang.String" value="Bob"/>
        <constructor-arg index="1" type="int" value="20"/>
    </bean>
    <!--person3-->
    <bean id="person3" class="bean.Person">
        <property name="name" value="#{person1.name}"/>
        <property name="age" value="#{person2.age}"/>
    </bean>

执行结果:

猜你喜欢

转载自blog.csdn.net/swadian2008/article/details/113884142