05-spring-bean注入
spring中只有两大核心技术:
控制反转(IOC)&依赖注入(DI),AOP(面向切面编程)
依赖注入:指利用配置文件的关系,来决定类之间的引用关系,以及数据的设置操作。
构造方法注入
默认在applicationContext文件中配置的程序都可以自动通过spring容器加载时自动对对象实例化。
但是自动进行初始化的时候,调用的是类中的无参构造方法,而且通过反射机制可以知道,无参构造方法一定比有参构造方法的实例化更容易。
但是spring简化了反射的处理机制。利用spring中的动态的特性可以直接明确调用构造方法参数。
构造注入之前的文章已经有了,这里只补充前面没有的内容。
02-spring学习-配置bean
除了有之前的通过index,参数类型配置bean。
还能使用参数名称描述构造方法
Dept类:
package com.Spring.Demo; import java.beans.ConstructorProperties; public class Dept { private Integer deptno; private String name; @ConstructorProperties(value={"paramDeptno","paramDeptName"}) public Dept(Integer deptno, String name) { this.deptno = deptno; this.name = name; } @Override public String toString() { return "Dept [deptno=" + deptno + ", name=" + name + "]"; } }
调用这个方法:
package com.Spring.Demo; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestDept { public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); Dept dept=ctx.getBean("dept",Dept.class); System.out.println(dept); } }
Dept.java类 设置参数名称:
@ConstructorProperties(value={"paramDeptno","paramDeptName"}) public Dept(Integer deptno, String name) { this.deptno = deptno; this.name = name; }
也就是说设置的时候可以使用paramDeptno来代替索引0,paramDeptName代替索引1。
利用参数名称进行设置:
<bean id="dept" class="com.Spring.Demo.Dept"> <constructor-arg name="paramDeptno" value="10" ></constructor-arg> <constructor-arg name="paramDeptName" value="开发部门" ></constructor-arg> </bean>
真使用构造方法,还是使用参数的类型和顺序编写比较方便。
setter和getter注入
指通过属性的getter和setter方法,在配置中配置属性名称值。
具体看这里的各种属性配置
03-spring学习-属性配置细节
但是这里补充一点,对应布尔值类的设置,在spring中支持以下几种方式:
true/false,1/0,on/off,yes/no。
如果类中属性是boolean(注意首字母小写)型数据,返回的时候一般建议使用is开头(如下面例子isClose),但是也可以使用getter命名。
例子:
Dept类:
package com.Spring.Demo; import java.beans.ConstructorProperties; public class Dept { private Integer deptno; private String name; private boolean close; public boolean isClose() { return close; } public void setClose(boolean close) { this.close = close; } public Integer getDeptno() { return deptno; } public void setDeptno(Integer deptno) { this.deptno = deptno; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Dept [deptno=" + deptno + ", name=" + name + ", close=" + close + "]"; } }
调用:
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); Dept dept=ctx.getBean("dept",Dept.class); System.out.println(dept);
参数配置:
<bean id="dept" class="com.Spring.Demo.Dept"> <property name="deptno" value="34"></property> <property name="name" value="开发部门"></property> <property name="close" value="no"></property> </bean>
上面使用no配置Boolean属性,运行结果:
Dept [deptno=34, name=开发部门, close=false]
注入集合数据
支持:数组,LIST,Set,Map,properties。
同样看前面文档里面的连接。
这里做点补充:
一,操作数组注入:
company类:
package com.Spring.Demo; import java.util.Arrays; public class Company { private String msg[]; private Integer data[]; public String[] getMsg() { return msg; } public void setMsg(String[] msg) { this.msg = msg; } public Integer[] getData() { return data; } public void setData(Integer[] data) { this.data = data; } @Override public String toString() { return "Company [msg=" + Arrays.toString(msg) + ", data=" + Arrays.toString(data) + "]"; } }
配置:
<bean id="company" class="com.Spring.Demo.Company"> <property name="data"> <array value-type="java.lang.Integer"> <value>10</value> <value>20</value> <value>30</value> </array> </property> <property name="msg"> <array value-type="java.lang.String"> <value>mldn</value> <value>java-mldn</value> </array> </property> </bean>
我们发现,在使用数组数据的时候,设置了相应的数据类型,如果不写操作类型,那么spring会自动判断给出的数据类型,帮助用户自动转型。
调用:
package com.Spring.Demo; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestCompany { public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); Company cmp=ctx.getBean("company",Company.class); System.out.println(cmp); } }
运行结果:
Company [msg=[mldn, java-mldn], data=[10, 20, 30]]
但是需要清楚,数组一般不会在开发中出现,如果真出现,使用List集合横向代替数组。
Set和List注入:
假如上面集合类型是数组类型是List类型,就应该换成这样:
<bean id="company" class="com.Spring.Demo.Company"> <property name="data"> <list value-type="java.lang.Integer"> <value>10</value> <value>20</value> <value>30</value> </list> </property> <property name="msg"> <list value-type="java.lang.String"> <value>mldn</value> <value>java-mldn</value> </list> </property> </bean>
如果使用Set类型,配置也是如上,不需要改变,但是List和Set有个区别,Set集合里面的数据会自动去除重复。
注入Map集合:
company类:
package com.Spring.Demo; import java.util.Map; public class Company { private Map<Integer,String> msg; public Map<Integer, String> getMsg() { return msg; } public void setMsg(Map<Integer, String> msg) { this.msg = msg; } @Override public String toString() { return "Company [msg=" + msg + "]"; } }
配置:
<bean id="company" class="com.Spring.Demo.Company"> <property name="msg"> <map key-type="java.lang.Integer" value-type="java.lang.String"> <entry key="1" value="mldn"></entry> <entry key="2" value="java"></entry> </map> </property> </bean>
执行结果:
Company [msg={1=mldn, 2=java}]
以上的操作实际上见到的不多,而真正见过最多的是properties类型。
Properties注入:
company类:
package com.Spring.Demo; import java.util.Properties; public class Company { private Properties msg; public Properties getMsg() { return msg; } public void setMsg(Properties msg) { this.msg = msg; } @Override public String toString() { return "Company [msg=" + msg + "]"; } }
配置如下:
<bean id="company" class="com.Spring.Demo.Company"> <property name="msg"> <props> <prop key="mdln">mldn.com</prop> <prop key="java">java.com</prop> </props> </property> </bean>
在一些框架整合中,此类属性的设置(properties)是最为常见的。
内部引用
现在所给出的实际上是只是定义一些数值,而最神奇的是他可以定义文件内部的引用关系。
观察如下结构:
假如一个公司有很多部门,所有在公司类里面加入一个部门集合变量。
package com.Spring.Demo; import java.util.List; import java.util.Properties; public class Company { private Properties msg; private List<Dept> depts; public Properties getMsg() { return msg; } public void setMsg(Properties msg) { this.msg = msg; } public List<Dept> getDepts() { return depts; } public void setDepts(List<Dept> depts) { this.depts = depts; } @Override public String toString() { return "Company [msg=" + msg + ", depts=" + depts + "]"; } }
另外Dept结构如下:
package com.Spring.Demo; public class Dept { private Integer deptno; private String name; private boolean close; public boolean isClose() { return close; } public void setClose(boolean close) { this.close = close; } public Integer getDeptno() { return deptno; } public void setDeptno(Integer deptno) { this.deptno = deptno; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Dept [deptno=" + deptno + ", name=" + name + ", close=" + close + "]"; } }
配置如下:
<bean id="dept1" class="com.Spring.Demo.Dept"> <property name="deptno" value="34"></property> <property name="name" value="开发部门"></property> <property name="close" value="no"></property> </bean> <bean id="dept2" class="com.Spring.Demo.Dept"> <property name="deptno" value="34"></property> <property name="name" value="开发部门"></property> <property name="close" value="no"></property> </bean> <bean id="dept3" class="com.Spring.Demo.Dept"> <property name="deptno" value="34"></property> <property name="name" value="开发部门"></property> <property name="close" value="no"></property> </bean> <bean id="dept4" class="com.Spring.Demo.Dept"> <property name="deptno" value="34"></property> <property name="name" value="开发部门"></property> <property name="close" value="no"></property> </bean> <bean id="company" class="com.Spring.Demo.Company"> <property name="msg"> <props> <prop key="mdln">mldn.com</prop> <prop key="java">java.com</prop> </props> </property> <property name="depts"> <list> <ref bean="dept1"/> <ref bean="dept2"/> <ref bean="dept3"/> <ref bean="dept4"/> </list> </property> </bean>
由于集合里面的变量类型是自定义类类型,里面还有各种变量,这里用ref引用来设置。
所有可以在程序中的配置关系,现在完全可以通过配置文件横向替代了。