Spring part 1
Spring 框架概述
Spring上一个分层的Java开源框架,以IoC(反转控制)和AOP(面向切面编程)为内核
Spring的优势
- 方便解耦,简化开发
- AOP编程的支持
- 声明式事物的支持
- 方便程序测试
- 方便继承各种优秀框架
- 降低Java EE API的使用难度
Spring 7大模块
- Spring Core
- Spring AOP
- Spring ORM
- Spring DAO
- Spring Web
- Spring Context
- Spring Web MVC
IOC 理论推导
原来的步骤
- UserDao 接口
- UserDaoImpl 实现类
- UserService 业务接口
- 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配置
- id bean的唯一标识符,相当于对象名
- class Bean对象所对应的类型
- name 别名,name可以同时取多个别名
- 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
- singletion 单例
- 创建的所有实例只有一个
- prototype 原型
- 每一次创建都是单独的对象
- request
- session
- application
- 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