4.依赖注入DI
依赖:指Bean对象的创建依赖于容器 . Bean对象的依赖资源 .即由Spring创建bean。
注入:指Bean对象所依赖的资源 , 由容器来设置和装配 .即由Spring给创建bean中的属性赋值,给属性注入值。
4.1构造器注入
使用构造其注入,说明该bean对应的类,必须要有一个有参构造方法:
public class Hello {
private String str;
public Hello() {
System.out.println("构造器创建hello");
}
public Hello(String str) {
System.out.println("构造器创建hello");
this.str = str;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
}
xml配置(三种方式):
<!--name,根据有参构造方法参数名字注入-->
<bean id="hello" class="pojo.Hello">
<constructor-arg value="hello" name="str"/>
</bean>
<!--index,根据有参构造方法参数位置注入,0开始-->
<bean id="hello" class="pojo.Hello">
<constructor-arg value="hello" index="0"/>
</bean>
<!--type-->
<bean id="hello" class="根据有参构造方法参数类型注入">
<constructor-arg value="hello" type="java.lang.String"/>
</bean>
对于上述的3种方式建议使用第一种。
4.2set方式注入
set方式注入,在xml中bean的property属性的name是对应的是set函数名除去set后首字母小写得到的。
如果set后面的名字改变了,那么name=“”对应的值也要改变,这样Spring找到set方法。
Address类:
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Address{" +
"address='" + address + '\'' +
'}';
}
}
Student类
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 String wife;
private Properties info;
public Student() {
}
public Student(String name, Address address, String[] books, List<String> hobbys, Map<String, String> card, Set<String> games, String wife, Properties info) {
this.name = name;
this.address = address;
this.books = books;
this.hobbys = hobbys;
this.card = card;
this.games = games;
this.wife = wife;
this.info = info;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String[] getBooks() {
return books;
}
public void setBooks(String[] books) {
this.books = books;
}
public List<String> getHobbys() {
return hobbys;
}
public void setHobbys(List<String> hobbys) {
this.hobbys = hobbys;
}
public Map<String, String> getCard() {
return card;
}
public void setCard(Map<String, String> card) {
this.card = card;
}
public Set<String> getGames() {
return games;
}
public void setGames(Set<String> games) {
this.games = games;
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
public Properties getInfo() {
return info;
}
public void setInfo(Properties info) {
this.info = info;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address +
", books=" + Arrays.toString(books) +
", hobbys=" + hobbys +
", card=" + card +
", games=" + games +
", wife='" + wife + '\'' +
", info=" + info +
'}';
}
}
复杂类型注入:
引用类型
<property name="address" ref="address"/>
基本类型
<property name="name" value="jack"/>
数组
<property name="books">
<array>
<value>javase</value>
<value>1</value>
<value>javame</value>
<value>spring</value>
</array>
</property>
list
<property name="hobbys">
<list>
<value>sing</value>
<value>dance</value>
</list>
</property>
map
<property name="card">
<map>
<entry key="1" value="123456"/>
<entry key="idcard" value="789456"/>
</map>
</property>
set
<property name="games">
<set>
<value>lol</value>
<value>cf</value>
</set>
</property>
Propertis
<property name="info">
<props>
<prop key="name">jack</prop>
<prop key="wife">null</prop>
</props>
</property>
null
<property name="wife">
<null/>
</property>
4.3拓展方式注入
需要导入约束
导入p命名空间约束 : xmlns:p="http://www.springframework.org/schema/p"
导入c命名空间约束 : xmlns:c="http://www.springframework.org/schema/c"
User类
public class User {
private String name;
private int age;
public User(){
}
public User(String name,int age){
this.name = name;
this.age = age
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
p空间:
<!--P(属性: properties)命名空间 , 属性依然要设置set方法-->
<bean id="user" class="pojo.User" p:name="jack" p:age="18"/>
c空间:构造器注入
<!--C(构造: Constructor)命名空间 , 属性依然要设置set方法-->
<bean id="user" class="com.kuang.pojo.User" c:name="狂神" c:age="18"/>
4.4bean的作用域
范围 | 描述 |
---|---|
Singleton | 该bean为单例,即在Spring创建bean的时候,是以单例模式的方式创建的,我们在从容器获得多次获得该类对应的bean时,他们其实是一个对象。 |
prototype | 该bean为原型,即在Spring创建bean的时候,是以原型模式的方式创建的,我们在从容器获得多次获得该类对应的bean时,他们其实是不同的对象,每次获取Spring都会帮你实例的 |
request | 将单个bean定义的范围限定为单个HTTP请求的生命周期。也就是说,每个HTTP请求都有一个自己的bean实例,它是在单个bean定义的后面创建的。仅在可感知网络的Spring上下文中有效ApplicationContext 。 |
session | 将单个bean定义的范围限定为HTTP的生命周期Session 。仅在可感知网络的Spring上下文中有效ApplicationContext 。 |
application | 将单个bean定义的作用域限定为的生命周期ServletContext 。仅在可感知网络的Spring上下文中有效ApplicationContext 。 |
websocket | 将单个bean定义的作用域限定为的生命周期WebSocket 。仅在可感知网络的Spring上下文中有效ApplicationContext 。 |
Singleton:
<bean name="address" class="pojo.Address" scope="singleton">
<property name="address" value="家"/>
</bean>
@Test
public void address(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Address address1= context.getBean("address", Address.class);
Address address2= context.getBean("address", Address.class);
System.out.println(address1 == address2);
System.out.println(address1.hashCode());
System.out.println(address2.hashCode());
}
结果:
prototype:
<bean name="address" class="pojo.Address" scope="prototype">
<property name="address" value="家"/>
</bean>
@Test
public void address(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Address address1= context.getBean("address", Address.class);
Address address2= context.getBean("address", Address.class);
System.out.println(address1 == address2);
System.out.println(address1.hashCode());
System.out.println(address2.hashCode());
}
结果: