参考什么是spring,它能够做什么? 参考w3cschool 参考Spring框架入门教程
Spring框架的核心功能之一就是通过依赖注入的方式来管理Bean之间的依赖关系。
1 依赖注入
Spring依赖注入(Dependency Injection,DI)和控制反转含义相同,它们是从两个角度描述的同一个概念。使用依赖注入可以更轻松的管理和测试应用程序。
当某个Java实例需要另一个Java实例时,传统的方法是由调用者创建被调用者的实例(例如,使用new关键字获得被调用者实例),而使用Spring框架后,被调用者的实例不再由调用者创建,而是由Spring容器创建,这称为控制反转。
Spring容器在创建被调用者的实例时,会自动将调用者需要的对象实例注入给调用者,调用者通过Spring容器获得被调用者实例,这称为依赖注入。
依赖注入主要有两种实现方式,分别是setter注入(又称设值注入)和构造函数注入。具体介绍如下。
(1)构造函数注入
指IoC容器使用构造函数注入被依赖的实例。
可以通过调用带参数的构造函数实现依赖注入,每个参数代表一个依赖。
(2)setter注入
指IoC容器使用setter方法注入被依赖的实例。通过调用无参构造器或无参static工厂方法实例化Bean后,调用该Bean的setter方法,即可实现基于setter的DI。
在Spring实例化Bean的过程中,首先会调用默认的构造方法实例化Bean对象,然后通过Java的反射机制调用setXxx()方法进行属性的注入。因此setter注入要求Bean的对应类必须满足以下两点要求。
必须提供一个默认的无参构造方法。
必须为需要注入的属性提供对应的setter方法。
使用setter注入时,在Spring配置文件中,
需要使用<bean>元素的子元素<property>为每个属性注入值。
而使用构造注入时,在配置文件中,
主要使用<constructor-arg>标签定义构造方法的参数,
使用其value属性(或子元素)设置该参数的值。1.1 构造函数注入
使用<constructor-arg>标签实现构造函数注入。
在<constructor-arg>标签中,包含ref、value、type、index等属性。
value属性用于注入基本数据类型以及字符串类型的值;
ref属性用于注入已经定义好的Bean;
type属性用于根据参数类型进行注入;
index属性当构造函数有多个参数时,从0开始指定参数的位置。1.1.1 文件Man.java
package net.biancheng;
public class Man {
private String name;
private int age;
public Man() {
System.out.println("在man的构造函数内");
}
public Man(String name, int age) {
System.out.println("在man的有参构造函数内");
= name;
this.age = age;
}
public void show() {
System.out.println("名称:" + name + "\n年龄:" + age);
}
public String getName() {
return name;
}
public void setName(String name) {
= name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}1.1.2 文件Person.java
package net.biancheng;
public class Person {
private Man man;
public Person(Man man) {
System.out.println("在Person的构造函数内");
this.man = man;
}
public void man() {
man.show();
}
}1.1.3 文件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
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="man123" class="net.biancheng.Man">
<constructor-arg value="lucy"/>
<constructor-arg value="12"/>
</bean>
<bean id="person123" class="net.biancheng.Person">
<constructor-arg ref="man123"/>
</bean>
</beans>1.1.4 文件MainApp.java
package net.biancheng;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
Person person = (Person) context.getBean("person123");
person.man();
}
}输出如下所示
在man的有参构造函数内
在Person的构造函数内
名称:lucy
年龄:121.2 setter注入
使用<property>标签实现setter注入。
在<property>标签中,包含 name、ref、value 等属性。
name用于指定参数名称;
value属性用于注入基本数据类型以及字符串类型的值;
ref属性用于注入已经定义好的Bean。1.2.1 文件Man.java【不变】
package net.biancheng;
public class Man {
private String name;
private int age;
public Man() {
System.out.println("在man的构造函数内");
}
public Man(String name, int age) {
System.out.println("在man的有参构造函数内");
= name;
this.age = age;
}
public void show() {
System.out.println("名称:" + name + "\n年龄:" + age);
}
public String getName() {
return name;
}
public void setName(String name) {
= name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}1.2.2 文件Person.java【改变】
package net.biancheng;
public class Person {
private Man man;
public Man getMan() {
return man;
}
public void setMan(Man man) {
System.out.println("在Person的setMan函数内");
this.man = man;
}
public void man() {
man.show();
}
}1.2.3 文件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
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="person123" class="net.biancheng.Person">
<property name="man" ref="man123" />
</bean>
<bean id="man123" class="net.biancheng.Man">
<property name="name" value="lily" />
<property name="age" value="18" />
</bean>
</beans>1.2.4 文件MainApp.java【不变】
package net.biancheng;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
Person person = (Person) context.getBean("person123");
person.man();
}
}输出如下:
在man的构造函数内
在Person的setMan函数内
名称:lily
年龄:18每个基于应用程序的java都有几个对象,由这些对象一起工作来呈现出终端用户所看到的工作的应用程序。当编写一个复杂的Java应用程序时,应用程序类应该尽可能独立于其他Java类来增加这些类重用的可能性,并且在做单元测试时,测试独立于其他类的独立性。依赖注入(或有时称为布线)有助于把这些类粘合在一起,同时保持他们独立。
假设你有一个包含文本编辑器组件的应用程序,并且你想要提供拼写检查。
(1)标准代码如下
public class TextEditor {
private SpellChecker spellChecker;
// 构造函数
public TextEditor() {
spellChecker = new SpellChecker();
}
}在这里我们所做的就是创建一个TextEditor和SpellChecker之间的依赖关系。
(2)在控制反转IoC的场景中如下
public class TextEditor {
private SpellChecker spellChecker;
// 构造函数
public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
}
















