Spring part 1

Scroll Down

Spring part 1

Spring 框架概述

Spring上一个分层的Java开源框架,以IoC(反转控制)和AOP(面向切面编程)为内核

Spring的优势

  1. 方便解耦,简化开发
  2. AOP编程的支持
  3. 声明式事物的支持
  4. 方便程序测试
  5. 方便继承各种优秀框架
  6. 降低Java EE API的使用难度

Spring 7大模块

  1. Spring Core
  2. Spring AOP
  3. Spring ORM
  4. Spring DAO
  5. Spring Web
  6. Spring Context
  7. Spring Web MVC

IOC 理论推导

原来的步骤

  1. UserDao 接口
  2. UserDaoImpl 实现类
  3. UserService 业务接口
  4. UserServiceImpl 实现类

在原来的代码中,用户更改一个需求需要更改很多代码,如果代码量很大,代价很高。

如果使用Set接口注入,就可以实现灵活的更换实现方式
之前,程序上主动创建对象,控制权在程序员手上,使用Set注入,程序不再具有主动性,程序只负责被动接收对象。
程序员不用去管理去管理对象的创建了
控制反转了,主动权交给用户了,IOC的原型

在Spring中通过xml配置来创建对象

<?xml version="1.0" encoding="ISO-8859-1"?>
<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 id="student" class="com.test.pojo.Student">
        <property name="age" value="10"/>
        <property name="name" value="lucas"/>
    </bean>
    
</beans>

Student是一个拥有Getter和Setter方法的Java对象

public class Student {
    private String name;
    private int age;
    ...
}

测试方法

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");    //核心对象
Student student = applicationContext.getBean("student", Student.class); //这里创建的对象是单例模式
System.out.println(student);

Spring 配置

别名 alias

如果添加了别名,也可以通过别名获取对象

Bean配置

  1. id bean的唯一标识符,相当于对象名
  2. class Bean对象所对应的类型
  3. name 别名,name可以同时取多个别名
  4. scope 单例或者原型

import

一般用于团队开发,可以将多个配置文件导入合并成一个
内容相同也会被合并

依赖注入 DI

构造器注入

这里声明了Student类的带参构造器

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

xml 的配置方法

<?xml version="1.0" encoding="ISO-8859-1"?>
<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 id="student" class="com.test.pojo.Student">
        <constructor-arg name="age" value="18"/>
        <constructor-arg name="name" value="lucas"/>
    </bean>

</beans>

最后说一个东西叫循环注入

Circular dependencies

For example: Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection. If you configure beans for classes A and B to be injected into each other, the Spring IoC container detects this circular reference at runtime, and throws a BeanCurrentlyInCreationException

比如说一个类A通过构造器注入需要一个B类的实例,B通过构造器注入也需要一个A的实例,就会被IoC 容器检测出来,然后报一个BeanCurrentlyInCreationException异常

set方式注入

  • 依赖:bean对象的创建依赖于容器
  • 注入:bean对象中的属性由容器注入

set注入

先更改一下Student类,使里面的属性包含基本上所有Collection集合

public class Student {
    private String name;
    private int age;
    private Set<String> books;
    private Map<String,Integer> cards;
    private Properties properties;
    private List<String> hobbies;
    private String[] schools;
    ...
    }

其中都包含了Getter和Setter方法

<?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 id="student" class="com.test.pojo.Student">
    <property name="name" value="lucas"/>
    <property name="age" value="20"/>
    <property name="books">
        <set>
            <value>c++从入门到放弃</value>
            <value>Java从入门到放弃</value>
            <value>Python从入门到放弃</value>
            <value>Spring从入门到放弃</value>
        </set>
    </property>
    <property name="cards">
        <map>
            <entry key="学生卡" value="2111111"/>
            <entry key="银行卡" value="1222222253"/>
            <entry key="电话卡" value="1345555555"/>
        </map>
    </property>
    <property name="hobbies">
        <list>
            <value>打游戏</value>
            <value>敲代码</value>
            <value>踢足球</value>
        </list>
    </property>
    <property name="properties">
        <props>
            <prop key="身高">180cm</prop>
            <prop key="体重">150kg</prop>
        </props>
    </property>
    <property name="schools">
        <array>
            <value>清华小学</value>
            <value>清华附中</value>
            <value>清华大学</value>
        </array>
    </property>
</bean>

</beans>

测试代码

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Student student = applicationContext.getBean("student", Student.class);
System.out.println(student);

测试结果

Student{name='lucas', age=20, books=[c++从入门到放弃, Java从入门到放弃, Python从入门到放弃, Spring从入门到放弃], cards={学生卡=2111111, 银行卡=1222222253, 电话卡=1345555555}, properties={体重=150kg, 身高=180cm}, hobbies=[打游戏, 敲代码, 踢足球], schools=[清华小学, 清华附中, 清华大学]}

拓展方式

p命名空间和c命名空间需要导入

xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"

p命名空间

属性注入的快捷写法
设置了name和age的值

<bean id="student" class="com.test.pojo.Student" p:name="lucas" p:age="20">
...
</bean>

c命名空间

构造器注入的快捷写法

<bean id="student1" class="com.test.pojo.Student" c:name="lucas" c:age="20"/>

Bean的作用域

BeanScope

  1. singletion 单例
    • 创建的所有实例只有一个
  2. prototype 原型
    • 每一次创建都是单独的对象
  3. request
  4. session
  5. application
  6. websocket

单例

<bean id="student" class="com.test.pojo.Student" p:name="lucas" p:age="20" scope="singleton">
</bean>

测试代码

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Student student1 = applicationContext.getBean("student", Student.class);
Student student2 = applicationContext.getBean("student", Student.class);
System.out.println(student1.hashCode());
System.out.println(student2.hashCode());

测试结果

282265585
282265585

原型

<bean id="student1" class="com.test.pojo.Student" c:name="lucas" c:age="20" scope="prototype"/>

测试代码

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Student student1 = applicationContext.getBean("student1", Student.class);
Student student2 = applicationContext.getBean("student1", Student.class);
System.out.println(student1.hashCode());
System.out.println(student2.hashCode());

测试结果

282265585
1297836716