依赖注入的方式
Spring Ioc容器如何注入Bean的依赖资源。 具体解释:
主要包括:
- 构造器注入: 容器实例化时Bean时注入的依赖。是通过在Bean定义中指定构造器参数进行注入依赖。包括实例工厂方法参数注入依赖。但静态工厂方法参数不允许注入依赖???Why。
- Setter注入: 通过Setter方法进行注入依赖。
具体实现:
1. 构造器注入: 通过配置构造器参数实现,构造器参数就是依赖。
(图片来自其他地方,觉得很好理解)
构造器类: 构造器注入/静态工厂/实例工厂方式见上一章
public class HelloImpl3 implements HelloApi {
private String message;
private int index;
//@java.beans.ConstructorProperties({"message", "index"})
public HelloImpl3(String message, int index) {
this.message = message;
this.index = index;
}
@Override
public void sayHello() {
System.out.println(index + ":" + message);
}
}
- 可以使用index/type/参数name来注入。
<constructor-arg index="0" value = "hello"/>
<constructor-arg index="1" value = "1"/>
<constructor-arg type="java.lang.String" value = "hello"/>
<constructor-arg type="int" value = "1"/>
<constructor-arg name="message" value = "hello"/>
<constructor-arg name="index" value = "1"/>
- 可以使用注解来注入依赖
在构造器上添加@java.beans.ConstructorProperties({“message”, “index”})
To Do—-待深入
2. Setter注入:
是通过构造器/静态工厂/实例工厂等实例化bean之后,通过使用set方法注入依赖。
Setter方式实际根据set名字注入的,例如setMessage则
<property name="message" value="Hello"/>
其中property说明是使用的setter方式注入,而message指的是setMessage方法。
JavaBean的约定:
1. set/get方法名遵守首字母大写,与属性名相同
2. javaBean 类为public, 必须要公共的无参构造器。
3. 属性为private
4. 属性必须通过set/get方法访问
5. 属性为 例如“URL”时,方法名setURL
2.1 常量注入
<property name="message" value="Hello"/>
<property name="index"><value>1</value></property>
value是个字符串,Spring容器会将value的字符串自动转化为属性类型。若转化出错抛出异常。
Spring对Boolean做了容错
true/false等于1/0等于yes/no等于on/off
2.2 注入集合类型(Set/List)
2.2.1 list
设置配置文件:
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 使用Setter方式注入-->
<bean name="setterlist" class="com.myspring.helloworld.HelloSetterList">
<!--指定构造器的参数-->
<property name="values">
<!--使用value-type设置list中的类型,
默认value为String类型,
也可以使用泛型如java.util.List<String> Spring容器自动识别泪表中的条目类型-->
<list value-type="java.lang.String">
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
</bean>
</beans>
设置javaBean Class:
package com.myspring.helloworld;
import java.util.List;
public class HelloSetterList {
private List<String> values;
public List<String> getValues() {
return values;
}
public void setValues(List<String> values) {
this.values = values;
}
}
设置测试类:
BeanFactory beanFactory = new ClassPathXmlApplicationContext("hellosetterlist.xml");
HelloSetterList listBean = beanFactory.getBean("setterlist", HelloSetterList.class);
System.out.println(listBean.getValues().size());
2.2.2 set
设置配置文件:
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 使用Setter方式注入-->
<bean name="setterset" class="com.myspring.helloworld.HelloSetterSet">
<!--指定构造器的参数-->
<property name="values">
<set>
<value>1</value>
<value>2</value>
<value>3</value>
</set>
</property>
</bean>
</beans>
设置java bean类:
package com.myspring.helloworld;
import java.util.Collection;
public class HelloSetterSet {
private Collection<String> values;
public void setValues(Collection<String> values) {
this.values = values;
}
public Collection<String> getValues() {
return values;
}
}
设置测试类:
BeanFactory beanFactory =
new ClassPathXmlApplicationContext("hellosetterset.xml");
HelloSetterSet listBean = beanFactory.getBean("setterset", HelloSetterSet.class);
System.out.println(listBean.getValues().size());
2.3 注入数组类型
类似于list
只是将 “list” 转化为 “array”
2.4 注入Map类型
只是将 “list” 转化为 “map”
属性类型需要使用key-type 与 value-type标签
使用 key 与 value标签制定键对应的值数据。外围用 entry标签标记。
2.5 注入Properties类型
只是将 “list” 转化为 “props”
使用 key 与 value标签制定键对应的值数据。外围用 prop标签标记。
2.6 引用其他Bean注入
2.6.1 注入依赖Bean
构造器方式
或
Setter方式
或
具体实现:
首先创建HelloApi实现类和HelloApiDecorator装饰类
HelloApiDecorator装饰类:
public class HelloApiDecorator implements HelloApi {
private HelloApi helloApi;
//空参构造器
public HelloApiDecorator() {
}
//有参构造器
public HelloApiDecorator(HelloApi helloApi) {
this.helloApi = helloApi;
}
public void setHelloApi(HelloApi helloApi) {
this.helloApi = helloApi;
}
@Override
public void sayHello() {
System.out.println("==========装饰一下===========");
helloApi.sayHello();
System.out.println("==========装饰一下===========");
}
}
创建配置文件:
<!-- 定义依赖Bean, HelloImpl类, HelloApi的实现类-->
<bean id="helloApi" class="com.myspring.helloworld.HelloImpl"/>
<!-- 通过构造器注入 -->
<bean id="bean1" class="com.myspring.helloworld.HelloApiDecorator">
<constructor-arg index="0" ref="helloApi"/>
</bean>
<!-- 通过Setter注入 -->
<bean id="bean2" class="com.myspring.helloworld.HelloApiDecorator">
<property name="helloApi"><ref bean="helloApi"/></property>
</bean>
ref local 与 ref parent配置方式
ref local 只能引用 id = “XXX”的方式,不能使用 name = “XXX”
ref parent 引用其他配置(官称父类)文件中的bean, 父类的bean名可以和本文件中的bean名重复。
具体实现:
父类配置文件, 一定要用id:
<!-- id 表示你这个组件的名字,class表示组件类-->
<!-- 使用默认的构造器-->
<bean name="default_constructor" class="com.myspring.helloworld.HelloConstrustor"> </bean>
<!-- 使用带参数的构造器,父类属性需要使用id-->
<bean id="argu_constructor" class="com.myspring.helloworld.HelloConstrustor">
<!--指定构造器的参数-->
<constructor-arg index="0" value = "hello argu construstor"/>
</bean>
子类的配置文件,包含ref local 和 ref parent引用:
<!-- 定义local的bean, 可以与父类同名-->
<bean id="argu_constructor" class="com.myspring.helloworld.HelloConstrustor">
<!--指定构造器的参数-->
<constructor-arg index="0" value = "hello local argu construstor"/>
</bean>
<!-- 通过local注入,使用id注入 -->
<bean id="local" class="com.myspring.helloworld.HelloApiDecorator">
<constructor-arg index="0"><ref local="argu_constructor"/></constructor-arg>
</bean>
<!-- 通过parent注入 -->
<bean id="parent" class="com.myspring.helloworld.HelloApiDecorator">
<property name="helloApi"><ref parent="argu_constructor"/></property>
</bean>
测试类:
//初始化父容器
ApplicationContext parentBeanContext =
new ClassPathXmlApplicationContext("helloconstructor.xml");
//初始化当前容器
ApplicationContext beanContext = new ClassPathXmlApplicationContext(
new String[] {"helloref.xml"}, parentBeanContext);
HelloApi bean1 = beanContext.getBean("local", HelloApi.class);
bean1.sayHelo();//该Bean引用local bean
HelloApi bean2 = beanContext.getBean("parent", HelloApi.class);
bean2.sayHelo();//该Bean引用parent bean
2.7 内部bean
内部bean对外部不可见。不能使用别名。
<bean id="bean" class="com.myspring.helloworld.HelloApiDecorator">
<property name="helloApi">
<bean id="helloApi" class="com.myspring.helloworld.HelloImpl"/>
</property>
</bean>
装饰工厂真是个好东西,面向接口编程。方便。