Spring~带你初步理解Spring(Bean容器、IOC、DI) 知道Spring框架配置使用流程

认识Spring

  • Spring 是另一个主流的 Java Web 开发框架,该框架是一个轻量级的应用框架,具有很高的凝聚力和吸引力。
  • 在实际开发中,通常服务器端采用三层体系架构,分别为表现层(web)、业务逻辑层(service)、持久层(dao)。
  • Spring 对每一层都提供了技术支持,在表现层提供了与 Struts2 框架的整合,在业务逻辑层可以管理事务和记录日志等,在持久层可以整合 Hibernate 和 JdbcTemplate 等技术。
  • 从设计上看,Spring 具有简单、可测试和松耦合等特点, 所以Spring 框架给予了 Java 程序员更高的自由度.

开发中使用Spring框架的好处

(1)方便解耦,简化开发
Spring 就是一个大工厂,可以将所有对象的创建和依赖关系的维护交给 Spring 管理。
(2)方便集成各种优秀框架
Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如 Struts2、Hibernate、MyBatis 等)的直接支持。
(3)降低 Java EE API 的使用难度
Spring 对 Java EE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等)都提供了封装,使这些 API 应用的难度大大降低。
(4)方便程序的测试
Spring 支持 JUnit4,可以通过注解方便地测试 Spring 程序。
(5)AOP 编程的支持
Spring 提供面向切面编程,可以方便地实现对程序进行权限拦截和运行监控等功能。
(6)声明式事务的支持
只需要通过配置就可以完成对事务的管理,而无须手动编程。

Spring体系结构

  • 我们常说的Spring其实是Spring Framework
  • Spring Framework 框架采用分层架构,根据不同的功能被划分成了多个模块,这些模块大体可分为 Data Access/Integration、Web、AOP、Aspects、Messaging、Instrumentation、Core Container 和 Test
  • Core Container 这是核心容器 是其他模块建立的基础 由Beans Core核心模块 Context上下文模块 和Expression Language 表达语言模块组成
  • Bean模块提供了BeanFactory 是工厂模式的经典实现 Spring将管理对象称为Bean
  • Core模块 提供了Spring框架的基本组成部分 包括IOC和DI功能
  • Context模块 上下文模块 建立在核心和Bean模块的基础之上 他是访问定义和配置任何对象的媒介
  • Expression Language模块 是运行时传和操作对象图的强大的表达式语言

Date Acc/Integration 是数据访问 集成层包括(JDBC ORM OXM等等)
Web 这层包括Web Servlet Struts和Porlet组件 可以极大的简化我们基于BS架构开发的项目
AOP 模块:提供了面向切面编程实现,允许定义方法拦截器和切入点,将代码按照功能进行分离,以降低耦合性。
Aspects 模块:提供与 AspectJ 的集成,是一个功能强大且成熟的面向切面编程(AOP)框架。
Instrumentation 模块:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用。
Test 模块:支持 Spring 组件,使用 JUnit 或 TestNG 框架的测试。

使用Spring框架需要配置的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>org.example</groupId>
    <artifactId>spring-study</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- Spring 需要的依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <!-- 日志需要的依赖 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

怎么理解我们的Spring

  • 理解Spring主要理解Core Container核心容器的三个核心
  1. Bean容器: 是提供管理Java对象的容器
  2. IOC : BeanFactory为IOC提供了完整的服务支持 简单来说, BeanFactory 就是一个管理 Bean容器所有对象的工厂,它主要负责初始化各种 Bean,并调用它们的生命周期方法。所以IOC是在在开发过程中 实例的创建不由调用者管理 , 而是由Spring创建并管理, Spring 容器会负责控制程序之间的关系,而不是由程序代码直接控制,因此,控制权由程序代码转移到了 Spring 容器中,控制权发生了反转,这就是 Spring 的 IOC 思想。
  3. Spring : 一个免费开源的轻量级的方便于企业应用开发的一个框架, 具有控制反转(IOC)和面向切面编程(AOP)等特性, 支持事务的处理和其他框架的整合
  4. 使用set注入, 使程序的主动性由主动变为被动, 由原先的主动new 到set的被动接收, 系统的耦合性大大降低, 可以专注于业务的实现, 这就是控制反转IOC的部分原型,
  5. IOC控制对象的反转是对于程序员而言反转了, 也就是不由程序员直接new, 而是让第三方传入, 对于我们程序员而言是被动接收
  6. 控制反转是一种编程思想, DI依赖注入是IOC实现的一种, 在没有IOC的时候, 我们使用面向对象编程, 所有对象的创建和对象之间的关系都是由程序员自己控制, 反转后就交给第三方set给我们程序员,
  7. 第三方包括xml配置文件或者注释, 通过这些第三方产生特定的对象, 并通过依赖注入完善对象, 这个过程也叫IOC控制反转, 所以spring中实现控制反转的是IOC编程思想, 实现依赖注入的是DI
  8. 当我们想要实现不同的操作, 只需要在配置文件中修改即可, 不用去动程序, 总之一句话:对象由spring去创建, 管理,装配, 这就是ioc ,
  9. DI : DI的含义是依赖的注入 其实还是给Bean容器中所有的对象提供服务支持, 本质就是给bean对象注入依赖属性 让每一个对象更加完整 更加有意义.
  10. IOC创建对象的方式: property走的无惨构造, 采用set传入 这是默认!
  11. 可以通过有参构造: 1. 下标构造constructor + index 建议使用 2. 类型构造 constructor + type 3. constructor + “参数名” 直接通过参数名
  12. 必须知道, 只要我们在配置文件中配置了bean 无论我们使用不使用, 他直接都帮我们实例化好了, 也就是无论我们是否getBean()他都已经创建好所有的bean了, 并且创建的只有一个, 即使我们在代码中get相同的bean俩次, 但是获得的是一个

使用依赖注入有俩种方式:

  1. 属性setter注入: 指 IoC 容器使用 setter 方法注入被依赖的实例。通过调用无参构造器或无参 static 工厂方法实例化 bean 后,调用该 bean 的 setter 方法,即可实现基于 setter 的 DI
  2. 构造方法注入: 指 IoC 容器使用构造方法注入被依赖的实例。基于构造器的 DI 通过调用带参数的构造方法实现,每个参数代表一个依赖

bean元素常用属性

  1. 需要让属性有 public 权限或者 setter 有 public 权限
  2. 基本数据类型 + String 用 value,其他引用类型用 ref
  3. 如果要使用集合,有 map、list、set 等直接使用

| id | 是一个 Bean 的唯一标识符,Spring 容器对 Bean 的配置和管理都通过该属性完成
| name | Spring 容器同样可以通过此属性对容器中的 Bean 进行配置和管理,name 属性中可以为 Bean 指定多个名称,每个名称之间用逗号或分号隔开
| class | 该属性指定了 Bean 的具体实现类,它必须是一个完整的类名,使用类的全限定名
| scope | 用于设定 Bean 实例的作用域,其属性值有 singleton(单例)、prototype(原型)、request、session 和 global Session。其默认值是 singleton
| constructor-arg | 元素的子元素,可以使用此元素传入构造参数进行实例化。该元素的 index 属性指定构造参数的序号(从 0 开始),type 属性指定构造参数的类型
| property | 元素的子元素,用于调用 Bean 实例中的 Set 方法完成属性赋值,从而完成依赖注入。该元素的 name 属性指定 Bean 实例中的相应属性名
| ref | 和 等元素的子元索,该元素中的 bean 属性用于指定对 Bean 工厂中某个 Bean 实例的引用
| value | 和 等元素的子元素,用于直接指定一个常量值
| list | 用于封装 List 或数组类型的依赖注入
| set | 用于封装 Set 类型属性的依赖注入
| map | 用于封装 Map 类型属性的依赖注入
| entry | 元素的子元素,用于设置一个键值对。其 key 属性指定字符串类型的键值,ref 或 value 子元素指定其值

代码演示

  • Person类
package Listen;

/**
 * Created with IntelliJ IDEA.
 * Description: If you don't work hard, you will a loser.
 * User: Listen-Y.
 * Date: 2020-08-10
 * Time: 20:54
 */
public class Person {

    private String name;
    private int age;

    public Person() {

    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

  • Teacher类
package Listen;

/**
 * Created with IntelliJ IDEA.
 * Description: If you don't work hard, you will a loser.
 * User: Listen-Y.
 * Date: 2020-08-11
 * Time: 15:25
 */
public class Teacher {

    private Person person;
    private String teacherId;

    public Teacher() {

    }

    public Teacher(Person person, String teacherId) {
        this.person = person;
        this.teacherId = teacherId;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public String getTeacherId() {
        return teacherId;
    }

    public void setTeacherId(String teacherId) {
        this.teacherId = teacherId;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "person=" + person +
                ", teacherId='" + teacherId + '\'' +
                '}';
    }
}

  • School类
package Listen;

import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * Description: If you don't work hard, you will a loser.
 * User: Listen-Y.
 * Date: 2020-08-11
 * Time: 15:26
 */
public class School {

    private List<Teacher> teachers;
    private String schoolName;

    public School() {

    }

    public School(List<Teacher> teachers, String schoolName) {
        this.teachers = teachers;
        this.schoolName = schoolName;
    }

    public List<Teacher> getTeachers() {
        return teachers;
    }

    public void setTeachers(List<Teacher> teachers) {
        this.teachers = teachers;
    }

    public String getSchoolName() {
        return schoolName;
    }

    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }

    @Override
    public String toString() {
        return "School{" +
                "teachers=" + teachers +
                ", schoolName='" + schoolName + '\'' +
                '}';
    }
}

  • 配置文件中的配置项的每个bean对象
<?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
                           https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 通过bean这个标签定义bean对象 Spring Bean容器是通过id来进行管理的 id代表的意思就是Spring可以通过id找到Bean
     如果没有提供id 会默认生成一个首字母小写的类名 一般建议都是写id的
     默认是单例模式-->
    <!-- 通过无惨的构造方法创建一个对象 如果该类型没有无惨的构造方法 就会报错 所以这个只支持有参构造方法 -->
    <bean id="love" class="java.lang.String" >
        <constructor-arg value="love" />
    </bean>

    <!-- 如果构造方法是无惨的可以使用这种进行设置属性 上面的叫构造方法注入 这叫属性setter注入(简称属性注入) -->
    <bean id="person" class="Listen.Person">
        <property name="name" value="listen" />
        <property name="age" value="21" />
    </bean>
    <!-- 通过构造方法创建一个person实例 -->
    <bean id="person2" class="Listen.Person">
        <constructor-arg name="name" value="frank" />
        <constructor-arg name="age" value="20" />
    </bean>

    <bean id="person3" class="Listen.Person">
        <property name="name" value="jake" />
        <property name="age" value="22" />
    </bean>

    <!-- 分别使用依赖注入和属性注入 创建实例  -->
    <bean id="teacher1" class="Listen.Teacher">
        <constructor-arg name="person" ref="person" />
        <constructor-arg name="teacherId" value="5201314"/>
    </bean>
    
    <bean id="teacher2" class="Listen.Teacher">
        <property name="person" ref="person2" />
        <property name="teacherId" value="7654321" />
    </bean>

    <bean id="teacher3" class="Listen.Teacher">
        <property name="person" ref="person3" />
        <property name="teacherId" value="1234567" />
    </bean>
    <!-- 注入带有集合的属性  -->
    <bean id="school" class="Listen.School">
        <property name="teachers">
            <list>
                <ref bean="teacher1" />
                <ref bean="teacher2" />
                <ref bean="teacher3" />
            </list>
        </property>
        <property name="schoolName" value="HappySchool" />
    </bean>

</beans>
  • 根据容器获取bean并且使用bean对象
import Listen.Person;
import Listen.School;
import Listen.Teacher;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        //加载配置文件
        //Spring开启容器的方式就是应用上下文(可以配置管理bean对象 及其他工作)
        //根据classpath路径 指定一个配置文件
        //根据配置文件完成配置工作(如bean的实例化)
        ApplicationContext context = new
                ClassPathXmlApplicationContext("applications.xml");

        //通过bean的名称获取bean对象
        String love =  (String)context.getBean("love");
        System.out.println(love);

        //通过类型获得bean对象 如果该类型有多个对象 就会报错  只支持一个该类型的对象 返回的是一个泛型对象可以忽略强转
        String love1 =  context.getBean(String.class);
        System.out.println(love1);
        System.out.println("====测试自定义类====");

        Person person = (Person) context.getBean("person");
        System.out.println(person);

        Person person2 = (Person)context.getBean("person2");
        System.out.println(person2);

        Person person3 = (Person)context.getBean("person3");
        System.out.println(person3);

        Teacher teacher1 = (Teacher)context.getBean("teacher1");
        System.out.println(teacher1);

        Teacher teacher2 = (Teacher)context.getBean("teacher2");
        System.out.println(teacher2);

        Teacher teacher3 = (Teacher)context.getBean("teacher3");
        System.out.println(teacher3);

        School school = (School)context.getBean("school");
        System.out.println(school);
    }
}
  • 运行结果
16:15:44.050 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6504e3b2
16:15:44.337 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 8 bean definitions from class path resource [applications.xml]
16:15:44.403 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'love'
16:15:44.495 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'person'
16:15:44.530 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'person2'
16:15:44.533 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'person3'
16:15:44.534 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'teacher1'
16:15:44.544 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'teacher2'
16:15:44.547 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'teacher3'
16:15:44.548 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'school'
love
love
====测试自定义类====
Person{name='listen', age=21}
Person{name='frank', age=20}
Person{name='jake', age=22}
Teacher{person=Person{name='listen', age=21}, teacherId='5201314'}
Teacher{person=Person{name='frank', age=20}, teacherId='7654321'}
Teacher{person=Person{name='jake', age=22}, teacherId='1234567'}
School{teachers=[Teacher{person=Person{name='listen', age=21}, teacherId='5201314'}, Teacher{person=Person{name='frank', age=20}, teacherId='7654321'}, Teacher{person=Person{name='jake', age=22}, teacherId='1234567'}], schoolName='HappySchool'}

Process finished with exit code 0

常见所有类型的注入

<?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创建对象, 在spring中这些都称为bean -->

    <bean id="address" class="hello.Address">
        <constructor-arg index="0" value="陕西省西安市"/>
    </bean>

    <bean id="student" class="hello.Student">
        <!--普通值注入-->
        <property name="name" value="Listen"/>
        <!--引用类型注入-->
        <property name="address" ref="address"/>
        <!--数组注入-->
        <property name="books">
            <array>
                <value>西游记</value>
                <value>水浒传</value>
                <value>三国演义</value>
            </array>
        </property>
        <!--List注入-->
        <property name="hobbes">
            <list>
                <value>听歌</value>
                <value>看电影</value>
                <value>跑步</value>
            </list>
        </property>
        <!--map注入-->
        <property name="cards">
            <map>
                <entry key="公交卡" value="101010"/>
                <entry key="学生卡" value="232323"/>
                <entry key="饭卡" value="776655"/>
            </map>
        </property>
        <!--set注入-->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>CF</value>
                <value>QQ</value>
            </set>
        </property>
        <!--空注入null-->
        <property name="wife">
            <null/>
        </property>
        <!--特殊类型-->
        <property name="info">
            <props>
                <prop key="父亲">XXX</prop>
                <prop key="母亲">YYY</prop>
            </props>
        </property>
    </bean>

</beans>

总结Spring框架配置使用的流程

  1. 加载配置文件 (加载.xml文件)
  2. 初始化: 根据配置文件中的配置项 进行初始化
  3. 使用: 根据容器获取到bean对象 (通过我们定义的配置项中的id获取 可以通过类型获取 但是如果该类型有多个对象 就会报错)
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值