Spring(一)IOC 依赖注入
Spring(一)IOC 依赖注入
1. Spring
Spring -> 春天! 软件行业的春天!
Spring是一个开源的Java/Java EE应用程序框架,它被设计用来简化企业级应用程序的开发。Spring的核心理念是通过提供一系列的服务,帮助开发者更好地管理对象间的依赖关系,以及更好地组织和结构化他们的应用程序代码。
以下是Spring框架的一些关键特性:
-
依赖注入(Dependency Injection):Spring框架通过依赖注入(DI)支持松耦合。DI使得组件之间的依赖关系可以通过配置文件或注解进行描述,而不是通过硬编码。
-
面向切面编程(Aspect-Oriented Programming):Spring支持面向切面编程,使得诸如日志记录、事务管理、安全等跨越多个对象层次的关注点可以被模块化和组织得更好。
-
事务管理:Spring提供了一套抽象接口以统一各种事务管理API,使得开发者可以使用一致的编程模型跨越不同的事务管理API(如JTA、JDBC、Hibernate、JPA等)。
-
Spring MVC:Spring的Web MVC框架是一个设计良好的、灵活的、强大的Web应用框架,它提供了一种清晰的分离控制器、模型对象、分派器和处理器对象的方式。
-
集成支持:Spring提供了对多种技术的集成支持,包括JDBC、Hibernate、JPA、JMS、RMI等。
-
测试:Spring提供了对JUnit和TestNG测试框架的一流支持,使得在Spring环境中进行单元测试和集成测试变得非常简单。
Spring的目标是使得Java/Java EE开发变得更加简单,同时也保持了高性能、健壮性和灵活性。
2. IOC 理论
相关博客 分享Iteye的开涛的精彩讲解
2.1 IOC 本质
控制反转loC(lnversion f Control),是一种设计思想,DI(依赖注入)是实现loC的一种方法,也有人认为DI
只是loC的另一种说法。没有loC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在
程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是: 获得
依赖对象的方式反转了。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体
Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转
的是loC容器,其实现方法是依赖注入 (Dependency Injection,DI)。
3. HelloSpring
这是我们接触Spring的第一个程序:
老样子,我们先上目录结构!👇
Hello.java 的代码:
package top.qwwq.pojo;
public class Hello {
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
}
beans.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">
<!--
类型 变量名 = new 类型()
Hello hello = new Hello()
id = 变量名
class = new 的对象
property 相当于给对象的属性设置一个值
-->
<!-- 使用Spring来创建对象,在Spring中这些都成为bean-->
<bean id="hello" class="top.qwwq.pojo.Hello">
<!--
ref: 引用Spring容器中创建好的对象
value: 具体的值,基本数据类型
-->
<property name="str" value="Spring"/>
</bean>
</beans>
最后再上我们的测试代码:
public class MyTest {
public static void main(String[] args) {
// 获取Spring的上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 我们的对象现在都在Spring中管理,我们要是用,直接去里面取出来就可以!
Hello hello = (Hello) context.getBean("hello");
System.out.println(hello.toString());
}
}
可以看出,我们再main
方法中并没有new
对象而是通过getBean
方法来获取到一个对象,这就是Spring中最重要的一个思想之一(IOC 控制反转),我们把对象交给Spring容器,
当我们有需要的时候,就告诉容器:我想要这个对象啦!!!!
容器就会把相应的对象给你,有时还会“贴心”地帮你赋值(这就是 依赖注入 在后面我们会说到), 每一个java类就是一个bean,我们把bean注册到Spring地配置文件中,Spring容器就会帮我们管理对象
4. IOC 创建对象的方式
上代码前,先来目录结构!
我们知道,Spring会帮助我们接管对象,但是!Spring到底是怎么帮助我们接管对象的呢?
在beans.xml中写道:
<!-- 无参构造-->
<bean id="user" class="top.qwwq.pojo.User">
<property name="name" value="EnderKC"/>
</bean>
<!-- 有参构造方法-->
<bean id="user2" class="top.qwwq.pojo.User" name="userNew,u2">
<constructor-arg name="name" value="EnderHKC"/>
</bean>
通过实验得知,Spring也是通过类地构造方法来创建对象。而且默认是用无参构造方法创建对象,使用set
方法来给对象注入值。当我们地类中有 有参构造方法 的时候,Spring也可以使用 有参构造方法 创建对象,并且用构造器给对象注入值(后面会提到)。
5. Spring 配置
5.1 别名
<alias name="student" alias="Stu"/>
<bean id="student" class="top.qwwq.pojo.Student"/>
可以通过在beans.xml中利用这种方式来给 已经在beans中注册了地类去别名 (跟MyBatis中不一样!)
5.2 Bean的配置
bean的配置
- id: bean的唯一表示符,也就是相当于我们学的对象名
- class: bean 对象所对应的权限定名 : 报名 + 类型
- name:也是别名,而且name更高级 可以同时取多个别名
5.3 import
如果我们刚好同时拥有两个Spring的配置文件,例如:一个用来管理beans,另一个用来管理MyBatis的东西。可以用到这个配置👇
<import resource="spring-dao.xml"/>
在applicationContext.xml中,导入spring-dao.xml的配置,可以让项目的配置看起来更加干净
6. 依赖注入
6.1 构造器注入
可以通过有参构造方法来给对象注入值
<!--有参构造方法-->
<bean id="user2" class="top.qwwq.pojo.User" name="userNew,u2">
<constructor-arg name="name" value="EnderHKC"/>
</bean>
java的代码:
private String name;
// 有参构造方法
public User(String name){
this.name = name;
}
用构造器注入的之后,就使用constructor-arg
标签
6.2 Set方法注入
<!-- 无参构造-->
<bean id="user" class="top.qwwq.pojo.User">
<property name="name" value="EnderKC"/>
</bean>
java代码
private String name;
// 无参构造方法
public User(){
System.out.println("User的无参构造");
}
用set注入,可以使用property
标签
6.3 拓展方式注入
假如!我们有一个类有非常多种类的属性,例如:👇
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private Properties info;
private String wife;
}
Spring也为我们提供了优雅的依赖注入方式:
<bean id="student" class="top.qwwq.pojo.Student">
<!-- 第一种 普通注入 value-->
<property name="name" value="EnderKC"/>
<!-- 第二种 bean注入 ref-->
<property name="address" ref="address"/>
<!-- 数组注入,ref-->
<property name="books">
<array>
<value>红楼梦</value>
<value>西游记</value>
<value>水浒传</value>
<value>三国演义</value>
</array>
</property>
<!-- List -->
<property name="hobbys">
<list>
<value>听歌</value>
<value>敲代码</value>
<value>看电影</value>
<value>打篮球</value>
</list>
</property>
<!-- MAP-->
<property name="card">
<map>
<entry key="身份证" value="111223334556788"/>
<entry key="银行卡" value="1235678432"/>
</map>
</property>
<!-- SET-->
<property name="games">
<set>
<value>LOL</value>
<value>BOB</value>
<value>COC</value>
</set>
</property>
<!-- null-->
<property name="wife">
<null/>
</property>
<!-- Properties-->
<property name="info">
<props>
<prop key="学号">1001</prop>
<prop key="性别">男</prop>
</props>
</property>
</bean>
6.4 bean的作用域
singleton 默认是单例模式 每获取的对象都是同一个
<bean id="user3" class="top.qwwq.pojo.User" p:name="Ender" p:age="17" scope="singleton"/>
原型模式 获取的每个对象都不相等
<bean id="user4" class="top.qwwq.pojo.User" p:name="Ender" p:age="17" scope="prototype"/>
验证:
// 单例模式 获取的对象是同一个 返回True
User user = (User) context.getBean("user3");
User user2 = (User) context.getBean("user3");
System.out.println(user == user2);
// 原型模式 每次从容器中get的时候都会得到一个新对象 返回false
User user3 = (User) context.getBean("user4");
User user4 = (User) context.getBean("user4");
System.out.println(user3 == user4);