文章目录
Setter注入方式用的最多
- Spring开发团队一般主张当实现的应用组件是不可变对象时使用构造器注入并且要保证所需的依赖不是null。
- 另一方面,大量的构造器参数造成糟糕的代码异味,这表明类可能承担了太多的职责应该需要重构以便更好的适当分离要解决的问题
- setter注入的一个好处是setter方法使得这个类的对象在以后的某个时候还可合理的重新配置或者重新注入,并且可读性好
构造器注入
通过构造方法实现注入
项目结构
Teacher.java
package com;
public class Teacher {
private int id;
private String name;
//无参数
public Teacher() {
}
//有参数
public Teacher(int id, String name) {
this.id = id;
this.name = name;
}
public void show() {
System.out.println("id:"+id+",name:"+name);
}
}
Test.java
package com;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
Teacher t = (Teacher)ctx.getBean("Teacher");
t.show();
}
}
Beans.xml
<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-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 构造器注入形式1,简单但是对顺序与数量有要求,必须与Teacher类一致才行 -->
<!--
<bean id="Teacher" class="com.Teacher">
<constructor-arg value="1"></constructor-arg>
<constructor-arg value="zhangSan"></constructor-arg>
</bean>
-->
<!-- 构造器注入形式2,通过id属性确定赋值目标 -->
<!--
<bean id="Teacher" class="com.Teacher">
<constructor-arg index="0" value="1"></constructor-arg>
<constructor-arg index="1" value="zhangsan"></constructor-arg>
</bean>
-->
<!-- 构造器注入形式3,通过name属性确定赋值目标 -->
<!--
<bean id="Teacher" class="com.Teacher">
<constructor-arg name="id" value="1"></constructor-arg>
<constructor-arg name="name" value="zhangsan"></constructor-arg>
</bean>
-->
</beans>
优缺点
代码简单,但是可读性差。
Setter方法注入
- 在调用了无参构造方法或者无参静态工厂方法实例化bean之后,容器通过回调bean的setter方法可以完成依赖注入。
如果注入的是引用类型,用ref属性,参数是上面定义的Bean的id;
简单类型的注入
项目结构
DiClass.java
package com;
import java.sql.DriverManager;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class DiClass {
private int id;
private String name;
private Teacher teacher;
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public void show() {
System.out.println(id);
System.out.println(name);
System.out.println("==========================");
teacher.show();
}
}
Teacher.java
package com;
public class Teacher {
private int id;
private String name;
//无参数
public Teacher() {
}
//有参数
public Teacher(int id, String name) {
this.id = id;
this.name = name;
}
public void show() {
System.out.println("id:"+id+",name:"+name);
}
}
Test.java
package com;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
DiClass dc = (DiClass)ctx.getBean("DiClass");
dc.show();
}
}
Beans.xml
<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-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 构造器注入形式1,简单但是对顺序与数量有要求,必须与Teacher类一致才行 -->
<!--
<bean id="Teacher" class="com.Teacher">
<constructor-arg value="1"></constructor-arg>
<constructor-arg value="zhangSan"></constructor-arg>
</bean>
-->
<!-- 构造器注入形式2,通过id属性确定赋值目标 -->
<!--
<bean id="Teacher" class="com.Teacher">
<constructor-arg index="0" value="1"></constructor-arg>
<constructor-arg index="1" value="zhangsan"></constructor-arg>
</bean>
-->
<!-- 构造器注入形式3,通过name属性确定赋值目标 -->
<bean id="Teacher" class="com.Teacher">
<constructor-arg name="id" value="1"></constructor-arg>
<constructor-arg name="name" value="zhangsan"></constructor-arg>
</bean>
---------------------------------------------------------------
<!-- ref的参数是上面定义的Bean的id -->
<bean id="DiClass" class="com.DiClass">
<property name="id" value="100"></property>
<property name="name" value="lisi"></property>
<property name="teacher" ref="Teacher" ></property>
</bean>
</beans>
复杂类型的注入
引用数据类型 & 匿名内部类/内部Bean
第二个就是匿名内部类,只能在哪地方一小块用。
List与数组
package com;
import java.sql.DriverManager;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class DiClass {
private List bookName;
private Set hobby;
public void setBookName(List bookName) {
this.bookName = bookName;
}
}
<!-- List类型与数组类型 -->
<property name="bookName">
<list>
<value>Java</value>
<value>c#</value>
<!-- ref=上面的自定义ID -->
<ref bean="Teacher"/>
</list>
</property>
Set
private Set hobby;
public void setHobby(Set hobby) {
this.hobby = hobby;
}
<!-- set类型,不会放重复的数据 -->
<property name="hobby">
<set>
<value>book</value>
<value>football</value>
<ref bean="Teacher"/>
<value>book</value>
</set>
</property>
Map
private Set hobby;
private Map map;
public void setMap(Map map) {
this.map = map;
}
<!-- HashMap -->
<property name="map">
<map>
<!-- key=键 ,value=数值 -->
<entry key="a" value="100"></entry>
<!-- key-ref=引用数据类型,加上ref的都是Bean的引用数据类型 -->
<entry key-ref="Teacher" value="200"></entry>
<entry key="b" value-ref="Teacher"></entry>
</map>
</property>
Properties
集合合并
模拟Java的继承
abstract属性定义为抽象,就不再具体实例化了,多用于模板