Spring基础(一)

237 阅读3分钟

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

IOC与DI

IOC:反转控制(inversion of control)的思想完全颠覆了应用程序组件获取资源的传统方式;反转了资源的获取方向——改由容器主动的将资源推送给需要的组件,开发人员不需要知道容器是如何创建对象的,只需要提供接收资源的方式即可,极大的降低了学习成本,提高了开发的效率。这种行为也称为查找的被动形式

DI:dependency injection是ioc的另一种表述形式;即组件以一些预先定义好的方式(例如:setter方法)接收来自于容器的资源注入。相对于ioc而言,这种表述更直接

结论:IOC就是一种反转控制的思想,而DI是对IOC的一种具体实现

IOC容器

spring的ioc容器就是ioc思想的一个落地产品的实现。ioc容器中管理的组件叫做bean。在创建bean之前,首先需要创建ioc容器。spring提供了ioc容器的两种实现方式

BeanFactory:这是IOC容器的基本实现,是spring内部使用的接口。面向spring本身,不提供给开发人员使用 ApplicationContext:BeanFactory的子接口,提供了更多高级的特性。面向spring的使用者,几乎所有的场合都使用ApplicationContext,而不是底层的BeanFactory

基于Xml文件来管理bean

依赖

<!--设置打包方式-->
<packaging>jar</packaging>
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.1</version>
    </dependency>
    <!--junit测试-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

helloworld对象

public class HelloWorld {
    public void sayHello(){
        System.out.println("Hello,Spring");
    }
}

spring配置文件

<?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">
    
    <!--ioc容器配置文件-->
    <!--id是bean的唯一标识,class是bean对象所对应的类型(将helloworld这个对象交给ioc容器来管理)-->
    <bean id="helloworld" class="com.sentiment.pojo.HelloWorld"></bean>
</beans>

测试类

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
​
public class SpringTest {
    @Test
    public void HelloWorldTest(){
        //通过配置文件获取ioc容器
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
        //从ioc中获取bean对象
        HelloWorld bean = (HelloWorld) ioc.getBean("helloworld");
        bean.sayHello();
    }
}

获取bean的三种方式

  • 根据bean的id获取
Student studentOne = (Student) ioc.getBean("studentOne");
  • 根据bean的类型获取
Student studentOne = ioc.getBean(Student.class);

注意:根据类型获取bean时,要求Ioc容器中有且只有一个类型匹配的bean

若没有任何一个类型匹配的bean,此时抛出异常:NoSuchBeanDefinitionException

若有多个类型匹配的bean,此时抛出异常:NouniqueBeanDefinitionException

  • 根据bean的id和类型获取
Student studentOne = ioc.getBean("studentOne", Student.class);

根据类型来获取bean时,在满足bean唯一性的前提下其实只是看:『对象instanceof指定的类型』的返回结果只要返回的是true就可以认定为和类型匹配,能够获取到。即通过bean的类型、bean所继承的类的类型、bean所实现的接口的类型都可以获取bean

扩展

若组件类实现了接口,可以根据接口获取bean,但若这个接口有多个实现类则无法获取即:若Student实现或继承了Persion类,则可以通过person获取student的bean

Person person = ioc.getBean(Person.class);

三种方式及扩展

public void testIoc(){
    ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    //Student studentOne = (Student) ioc.getBean("studentOne");
    //Student studentOne = ioc.getBean(Student.class);
    //Student studentOne = ioc.getBean("studentOne", Student.class);
    Person person = ioc.getBean(Person.class);
    System.out.println(person);
}

依赖注入

setter注入

配置

  • property:通过成员变量的set方法进行赋值
  • name :设置需要赋值的属性名(和set方法有关)
  • value:设置为属性所赋的值
<bean id="studentTwo" class="com.sentiment.pojo.Student">
    <property name="sid" value="1842"></property>
    <property name="sname" value="Sentiment"></property>
    <property name="age" value="20"></property>
    <property name="gender" value="男"></property>
</bean>

测试

public void testSetter(){
    ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    Student studentTwo = ioc.getBean("studentTwo", Student.class);
    System.out.println(studentTwo);
}

结果

此时通过property标签,对各个属性进行了赋值

Student{sid=1842, sname='Sentiment', age='20', gender='男'}

构造器注入

配置

若只有一个有参控制器,直接赋值即可

<bean id="studentThree" class="com.sentiment.pojo.Student">
    <constructor-arg value="1843"></constructor-arg>
    <constructor-arg value="Tana"></constructor-arg>
    <constructor-arg value="21"></constructor-arg>
    <constructor-arg value="男"></constructor-arg>
</bean>

测试

public void testByConstructor(){
    ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    Student studentThree = ioc.getBean("studentThree", Student.class);
    System.out.println(studentThree);
}

结果

Student{sid=1843, sname='Tana', age='21', gender='男'}

此时若再加一个属性并定义他的有参控制器

public Student(Integer sid, String sname, Double score, String gender) {
    this.sid = sid;
    this.sname = sname;
    this.score = score;
    this.gender = gender;
}

在执行后结果:

Student{sid=1843, sname='Tana', age='null', gender='男', score=21.0}

可以看到21想赋给age但,赋值给了score,所以在配置文件后边可以再加上一个name属性,来定义赋值对象

<constructor-arg value="21" name="age"></constructor-arg>

此时结果就赋给了age

Student{sid=1843, sname='Tana', age='21', gender='男', score=null}

\