目录
1.注入
1.什么是注入:
通过Spring工厂及配置文件,为所创建对象的成员变量赋值。
2.为什么需要注入
以前我们为对象的成员变量赋值,直接通过编码的方式,这样是存在耦合的
如果我们以后想为name属性,设置别的值。那么又要改代码,存在耦合性,所以我们将对象属性的设置放到配置文件中(属性注入)。
3.如何进行注入(开发步骤)
- 类的成员变量提供set get方法
- 配置spring的配置文件
<bean id="person" name="p1,p2" class="com.baizhiedu.basic.model.Person"> <property name="id"> <value>10</value> </property> <property name="name"> <value>*</value> </property> </bean>
4.注入的好处:
解耦合:日后属性需要改动的话,就不需要在代码层面修改了,到配置文件中修改。
2.注入原理分析(简易版)
1.类似前面的工厂原理分析:会根据配置文件,进行反射创建对象(最终调用构造方法)。注入会根据配置文件内容的property标签,调用set方法对属性赋值。
- Spring通过底层调用对象属性的set方法,完成成员变量的赋值,这种方法我们也称之为
set注入
。 - 会根据配置文件内容的property标签,调用set方法对属性赋值。
3.Set注入详解
1.针对不同类型的成员变量,我们在注入时,在<property>
标签中,需要嵌套不同的子标签。
2.可能遇到的各种Set注入的类型主要分为两大类
- JDK内置类型
- 用户自定义类型
3.1.Set注入JDK内置类型
1.8种基本类型+String
基本类型:字符类型char,布尔类型boolean以及数值类型byte、short、int、long、float、double。
property标签直接嵌套value标签
<bean id="person" name="p1,p2" class="com.baizhiedu.basic.model.Person">
<property name="id">
<value>10</value>
</property>
</bean>
2.数组类型:
property标签嵌套list标签,list标签再嵌套value标签
//Person类数组属性
private String[] email;
public String[] getEmail() {
return email;
}
public void setEmail(String[] email) {
this.email = email;
}
//applicationContext.xml
<bean id="person" name="p1,p2" class="com.baizhiedu.basic.model.Person">
<property name="email">
<list>
<value>sdaS@1.com</value>
<value>sdaS@2.com</value>
<value>sdaS@3.com</value>
</list>
</property>
</bean>
3.Set集合属性:
- 1.注意Set集合是无序的
//Person类Set属性
private Set<String> tels;
public Set<String> getTels() {
return tels;
}
public void setTels(Set<String> tels) {
this.tels = tels;
}
//applicationContext.xml
<bean id="person" name="p1,p2" class="com.baizhiedu.basic.model.Person">
<property name="tels">
<set>
<value>12312311313</value>
<value>12666611313</value>
<value>12789011313</value>
</set>
</property>
</bean>
- 2.注意:set标签里面不一定嵌套value,要根据Set<>泛型来决定。如果没有指定泛型,说明可以存任何对象,那么set标签可以同时嵌套value(8种基本类型+String),list(数组,list),ref标签(自定义对象)。
//Person类Set属性
private Set obj;
get/set
//applicationContext.xml
<bean id="person" name="p1,p2" class="com.baizhiedu.basic.model.Person">
<property name="tels">
<set>
<value>12312311313</value>
<ref bean="idz值"/>
<list>
<value>12313</value>
</list>
</set>
</property>
</bean>
4.List集合属性
- property标签嵌套list标签(同数组,因为list底层用的就是数组),list中嵌套的标签要根据List< E >泛型来决定。
- 注意:list元素是允许重复的,而且是有序的,输出顺序同赋值时的顺序。
<bean id="person" name="p1,p2" class="com.baizhiedu.basic.model.Person">
<property name="address">
<list>
<value>11111</value>
<value>2222</value>
<value>2222</value>
</list>
</property>
</bean>
5.Map集合属性
- Map的特点:键值对,每对键值对又是一个Map.Entry对象。
- key有特定的子标签,子标签根据对应的泛型类型选择;值没有子标签,且要根据对应的泛型类型选择。
- 注意:为什么在key标签和entry标签中嵌套了value标签,因为Map< String, String>属性的泛型是String, String。
- key标签的value标签:表示键的value;entry标签的value标签:表示值的value
<property name="qqs">
<map>
<entry>
<key><value>txl</value></key>
<value>1309984539</value>
</entry>
<entry>
<key><value>others</value></key>
<value>9999999</value>
</entry>
</map>
</property>
6.Properties集合属性
后面进行Spring与MyBatis的整合,需要大量的使用这个类型。
- Properties类型是一种特殊的Map:key和value都只能是String。
private Properties properties;
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
<property name="properties">
<props>
<prop key="sss">wwww</prop>
<prop key="eee">tttt</prop>
</props>
</property>
7.复杂的JDK类型(Date)
需要自定义类型转换器来处理。
3.2.Set注入用户自定义类型
1.第一种方式:
-
为成员变量提供set get方法
public class UserServiceImpl implements UserService { private UserDAO userDao; public UserDAO getUserDao() { return userDao; } public void setUserDao(UserDAO userDao) { this.userDao = userDao; } @Override public void register(User user) { userDao.register(user); } @Override public void login(String name, String password) { userDao.login(name, password); } }
-
配置文件中进行注入(赋值)
<bean id="userService" class="com.baizhiedu.basic.UserServiceImpl"> <property name="userDao"> <bean class="com.baizhiedu.basic.UserDAOImpl"></bean> </property> </bean>
-
第一种赋值方式存在的问题:
-
- 1.配置文件代码冗余:AServiceImpl需要userDao属性,BServiceImpl也需要userDao属性,那么配置文件中就需要写两句
<bean class="com.baizhiedu.basic.UserDAOImpl"></bean>
。如果更多的Service对象需要这个属性,配置文件中就需要写更多。
- 1.配置文件代码冗余:AServiceImpl需要userDao属性,BServiceImpl也需要userDao属性,那么配置文件中就需要写两句
-
- 2.每写一个bean标签就意味着创建了一个UserDao对象,所以被注入的对象属性(UserDao)多次创建,浪费(JVM内存资源)。
2.第二种方式:
- 注意:< ref bean=“userDao”>< /ref>中的bean属性是其他bean标签的id值。
<bean id="userDao" class="com.baizhiedu.basic.UserDAOImpl"></bean>
<bean id="userService" class="com.baizhiedu.basic.UserServiceImpl">
<property name="userDao">
<ref bean="userDao"></ref>
</property>
</bean>
- 注意:Spring4.x废除了< ref local = “”/>,这个语法基本等效于< ref bean=""/>
3.3.Set注入的简化写法
1.基于属性的简化:
- value属性,代替value标签:value属性只能用在JDK的八种基本类型+String类型。
<property name="id">
<value>10</value>
</property>
//value属性,代替value标签
<property name="id" value="10"></property>
<property name="userDAO">
<ref bean="userDAO"/>
</property>
//ref属性代替ref标签
<property name="userDAO" ref="userDAO"/>
2.基于命名空间p的简化:
命名空间p就相当于property标签的作用:
配置文件写法:
<bean id="person1" class="com.baizhiedu.basic.model.Person" p:name="tttxxxll" p:id="66666"></bean>
//等价于
<bean id="person1" class="com.baizhiedu.basic.model.Person">
<property name="id" value="66666"></property>
<property name="name">
<value>tttxxxll</value>
</property>
</bean>
<bean id="userDao" class="com.baizhiedu.basic.UserDAOImpl"></bean>
<bean id="userService1" class="com.baizhiedu.basic.UserServiceImpl" p:userDao-ref="userDao"/>
//等价于原写法
<bean id="userService" class="com.baizhiedu.basic.UserServiceImpl">
<property name="userDao">
<!--<bean class="com.baizhiedu.basic.UserDAOImpl"></bean>-->
<ref bean="userDao"></ref>
</property>
</bean>