Spring学习(1)之IoC和Di
文章目录
1.Spring
1.1简介
- 是一个大杂烩,使现有的技术更快的使用,整合了现有的所有的框架。
- 2002年,首次推出了SPring的框架的雏形:interface21框架。
- 创始人:Rod Johnson,Spring Framework创始人,著名作者。很难想象Rod Johnson的学历,真的让好多人大吃一惊,他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学。提出了著名的造*的理论。
现在的技术栈普遍是:
- SSH : Struct2 + Spring + Hibernate!
- SSM : SpringMvc + Spring + Mybatis!
Spring的获取的来源
官网:https://spring.io/projects/spring-framework#overview
官方下载地址: http://repo.spring.io/release/org/springframework/spring
GitHub:https://github.com/spring-projects/spring-framework
Spring的jar包:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
// 后期使用的时候,会对数据库进行相关的操作
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
1.2优点与缺点:
优点:
Spring是一个轻量级的控制反转(ioc)和面向切面编程(aop)的框架。
- 开源性
- 轻量级的,非入侵式的。
- 控制反转和,面向切面编程的。
- 支持对事务的处理,对框架的支持。
缺点:
配置十分的繁琐,被称为配置地狱。
1.3组成:
- Data Access/Integration层包含有JDBC、ORM、OXM、JMS和Transaction模块。
- Web层包含了Web、Web-Servlet、WebSocket、Web-Porlet模块。
- AOP模块提供了一个符合AOP联盟标准的面向切面编程的实现。
- Core Container(核心容器):包含有Beans、Core、Context和SpEL模块。
- Test模块支持使用JUnit和TestNG对Spring组件进行测试。
1.4提前知识:
- 现阶段的java开发会逐渐朝面向Spring开发进行。
- Springboot:
- 一个快速开发的一个脚手架(死模板,只需要记下来就好)
- 基于Springboot快速开发单个微服务。
- 约定大于配置?
- Spring Cloud:是基于Sping Boot 开发的
学习Spring boot最好的前提是学习Spring,只会使用Springboot不知道底层的原理,难以发展。
2.IoC的本质
中文的意思为控制反转,也可以将他理解为一个容器。
- 是一种的设计的思想,就是将原本在程序中创建对象的控制权,交由Spring框架进行管理。
- 正常控制:new一个对象
- 反控:如果要使用某个对象,是需要只需要从Spring容器获取需要使用的对象,不用关心对象的创建的过程,也就是将创建对象的控制权交给Spring框架。
示例:
-
创建一个Maven项目:
-
导入jar包:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.0.RELEASE</version> </dependency>
-
创建一个pojo类,使用了lombok
@Data public class Student implements Serializable { private int age; private String name; private char sex; }
-
再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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="student" class="com.g.pojo.Student"> <property name="age" value="100"/> <property name="name" value="李四"/> <property name="sex" value='男'/> </bean> </beans>
id就是对象的名字
-
再测试类中进行测试,获取到了该对象
public class MyTest { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = context.getBean("student", Student.class); System.out.println(student); } }
IoC的本质:Spring作为一个容器,需要shenm对象,由Spring进行创建,Spring底层会根据反射的原理找到对象的calss文件并对其中的字段进行赋值等操作(装配,依赖注入)。总之Ioc就是一种设计思想,di(依赖注入)是实现这种思想的一种方法。
2.1IoC创建对象的方式:
因为再实体类中不止有有参的构造也有无参构造,Spring会对创建的实体类进行装配时,会找不到Spring所需要的格式。
- 无参构造,和上面的例子一样的操作
- 有参构造,这个时候就需要使用构造器的方式进行属性的注入
例如:
对上面的xml文件进行修改:
<bean id="student" class="com.g.pojo.Student">
方法1:使用参数的下角标进行依赖注入值
<constructor-arg index="0" value="200"/>
方式2:使用参数的名称依赖植入
<constructor-arg name="name" value="王五"/>
方式3:使用参数的类型进行依赖注入(不推荐,因为肯定会重复的)
<constructor-arg type="char" value='女'/>
</bean>
3.Spring中xml文件中的属性的配置
3.1别名
xml文件:
<!--就是拓展了上面bean中的id的值-->
<alias name="student" alias="s"/>
测试类:
Student student = context.getBean("s", Student.class);
3.2Bean的配置
<!--
id : bean 的唯一标识符,也就是相当于我们学的对象名
class : bean 对象所对应的全限定名 : 包名 + 类型
name :也是别名,而且name 可以同时取多个别名
-->
<bean id="userT" class="com.kuang.pojo.UserT" name="user2 u2,u3;u4">
<property name="name" value="西部开源"/>
</bean>
3.3import
这个import,一般用于团队开发使用,他可以将多个配置文件,导入合并为一个
假设,现在项目中有多个人开发,这三个人复制不同的类开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的!
-
张三
-
李四
-
王五
-
applicationContext.xml
<import resource="beans.xml"/> <import resource="beans2.xml"/> <import resource="beans3.xml"/>
使用的时候,直接使用总的配置就可以了
每个人只需要写自己的实体类和xml配置文件就可以了。
3.4bean标签的作用域
-
单例模式 (Spring默认机制)
<bean id="s1" class="com.g.pojo.Student" scope="singleton"/>
-
原型模式:每次从容器中get的时候,都会产生一个新对象!
<bean id="s3" class="com.g.pojo.Student" scope="prototype"/>
测试:
public class MyTest { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student1 = context.getBean("s1", Student.class); Student student2 = context.getBean("s2", Student.class); Student student3 = context.getBean("s3", Student.class); //单例和单例 System.out.println(student1==student1); //单例和原型 System.out.println(student1==student3); } } true false
-
其余的 request、session、application、这些个只能在web开发中使用到!
4.Di【依赖注入】
4.1.普通注入,无参的bean
4.2.构造器注入:针对于有参构造
<bean id="student" class="com.g.pojo.Student">
方法1:使用参数的下角标进行依赖注入值
<constructor-arg index="0" value="200"/>
方式2:使用参数的名称依赖植入
<constructor-arg name="name" value="王五"/>
方式3:使用参数的类型进行依赖注入(不推荐,因为肯定会重复的)
<constructor-arg type="char" value='女'/>
</bean>
4.3.Set方式注入(引用型数据类型)
复杂的实体类的数据的注入
-
Student类
public class Student { private Address address; private String name; }
-
Address类
@Data public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
-
配置文件
<bean id="dizhi" class="com.g.pojo.Address"> <property name="address" value="陕西"/> </bean> <bean id="student" class="com.g.pojo.Student"> <property name="address" ref="dizhi"/> <property name="name" value="张三"/> </bean>
注意:student类的指向ref指向上面由Spring创建出来的对象dizhi
-
测试
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) context.getBean("student"); System.out.println(student); } }
-
执行结果
Student{address=Address(address=陕西)}
4.4复杂数据类型的属性注入
-
实体类:
@Data public class Student { private String name; private String[] books; private List<String> hobbys; private Map<String,String> card; private Set<String> games; private String wife; private Properties info; }
-
配置文件:
<bean id="student" class="com.g.pojo.Student"> <property name="name"> <value>张三</value> </property> <!--数组--> <property name="books"> <array> <value>天龙八部</value> <value>笑傲江湖</value> </array> </property> <!--list集合--> <property name="hobbys"> <list> <value>running</value> <value>swimming</value> <value>singing</value> </list> </property> <!--map集合--> <property name="card"> <map> <entry key="id" value="123456789"/> <entry key="name" value="张三"/> <entry key="sex" value="男"/> </map> </property> <!--set集合--> <property name="games"> <set> <value>lol</value> <value>csgo</value> </set> </property> <!--null注入--> <property name="wife"> <null/> </property> <!--properties--> <property name="info"> <props> <prop key="driver">driver</prop> <prop key="url">ssss</prop> <prop key="username">name</prop> <prop key="password">123456</prop> </props> </property> </bean>
-
测试:
public class MyTest { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) context.getBean("student"); System.out.println(student); } }
4.5拓展方式注入(c和p注入)
-
p命名空间注入,是普通注入的捷径
在配置文件中导入头文件,然后使用头文件:xmlns:p="http://www.springframework.org/schema/p" <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="student" class="com.g.pojo.Student" p:name="李四"/> </beans>
-
c命名空间的注入,是构造器注入的捷径,
使用方法:同理头文件:xmlns:c="http://www.springframework.org/schema/c" <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="student" class="com.g.pojo.Student" c:name="张三"/> </beans>