目录
本文须知
本文内容来自于B站孙帅suns的spring课程视频,由本人根据视频学习整理而成。然而,由于个人理解和整理的差异,可能存在部分地方的误差或讲解不够明确的情况。
为了获得更详细的课程内容和准确的解释,请您移步至B站,搜索孙帅suns获取详细课程视频内容,以便深入了解和学习。孙帅suns的视频将为您提供更全面、详细的知识和解释,帮助您更好地理解netty应用的相关内容。
在阅读本文时,请注意本文的目的是为了提供一个概述和个人整理的观点,而不是取代原始视频课程的内容。如有任何疑问或不明之处,建议您参考原始视频课程以获取更准确的信息。
感谢您的理解和支持!
在此附上B站对应课程视频链接:学不会Spring?因为你没有找对人
什么是注入
通过Spring工厂以及配置文件,为所创建的对象的成员变量赋值
为什么需要注入:
- 在之前的程序开发当中,当我们创建对象的时候,我们是通过类的set方法手动来给对象当中的属性赋值的,这个时候当我们想要修改对象的值的时候,就存在了耦合。
- 而通过注入的方式,以后我们需要对对应对象的属性进行更改的时候,只需要修改配置文件即可,不需要像之前一样修改代码同时重新编译、重新部署。
注入开发步骤
- 需要为类的成员变量提供相应的get、set方法
- 然后对配置文件进行配置:
public class Person {
private Integer id;
private String name;
private String[] emails;
private Set<String> tels;
private List<String> addr;
private Map<String, String> qqs;
private Properties p;
public Properties getP() {
return p;
}
public void setP(Properties p) {
this.p = p;
}
public Map<String, String> getQqs() {
return qqs;
}
public void setQqs(Map<String, String> qqs) {
this.qqs = qqs;
}
public List<String> getAddr() {
return addr;
}
public void setAddr(List<String> addr) {
this.addr = addr;
}
public Set<String> getTels() {
return tels;
}
public void setTels(Set<String> tels) {
this.tels = tels;
}
public String[] getEmails() {
return emails;
}
public void setEmails(String[] emails) {
this.emails = emails;
}
public Person() {
System.out.println("Person person");
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
<bean id="person" class="com.dida.pojo.Person">
<property name="id">
<value>10</value>
</property>
<property name="name">
<value>lihua<value>
</property>
</bean>
注入的原理分析
Spring会通过底层调用对象属性的set方法,完成成员变量的赋值,这种方式也称之为set注入。
而针对不同类型的成员变量,在<property>标签当中也需要嵌套其他的标签
set注入
JDK内置类型
- String和八种基本类型:通过<value></value>进行注入
- 数组类型:
<property name="emails">
<list>
<value>123@qq.com</value>
<value>222@qq.com</value>
<value>666@qq.com</value>
</list>
</property>
- set集合:
- 在set集合当中存储的数据存在重复的时候只会显示一个
- set集合需要根据泛型来判断标签当中嵌套什么标签
<!--set集合需要根据泛型来判断标签里面嵌套什么标签-->
<!--String和八大基本类型当泛型时-->
<property name="tels">
<set>
<value>11111111</value>
<value>22222222</value>
<value>33333333</value>
</set>
</property>
<!--以Object为泛型时-->
<property name="tels">
<set>
<ref bean>
<set> </set>
</set>
</property>
- List集合(存储String类型为例)
- List集合当中也可以嵌套其他类型,同时List类型支持重复的数据
<property name="addr">
<list>
<value>tianjin</value>
<value>wuhan</value>
<value>shanghai</value>
<value>shanghai</value>
<value>shanghai</value>
</list>
</property>
- Map集合(以存储String类型举例)
- map标签当中需要嵌套entry标签,同时key有特定的标签,而值根据类型选择标签
<property name="qqs">
<map>
<entry>
<key><value>suns</value></key> <!--键-->
<value>312312321312</value> <!--值-->
</entry>
</map>
</property>
- Properties类型(特殊的Map类型,key=String value=String)
- properties类型当中的键值都只能是字符串,所以这里的value标签省略了
<property name="p">
<props>
<prop key="a">aaa</prop>
<prop key="b">bbb</prop>
</props>
</property>
用户自定义类型
第一种方式:为成员变量提供set、get方法,然后在配置文件当中进行注入
<bean id="userService" class="com.dida.service.impl.userServiceImpl">
<property name="userDao">
<bean class="xxx.UserDaoImpl">
</bean>
</property>
</bean>
这种方式存在的问题:
- 配置文件代码冗余
- 被注入的对象UserDao会多次创建、浪费JVM的资源
第二种方式:提供set、get方法,配置文件当中再进行配置
<bean id="userDao" class="xxx.userDaoImpl"/>
<bean id="userService" class="com.dida.service.impl.userServiceImpl">
<property name="userDao">
<!--ref是引用,在这里用于将上面的bean userDao引用到此处-->
<ref bean="userDao"/>
</property>
</bean>
这种方式就相当于将成员变量向上提一级,这样在下面的bean中直接引用即可,这样即解决了冗余问题,也节省了资源。
set注入的简化写法
基于属性的简化
1. JDK类型注入
八种基本类型和String类型的改善
<bean id="person" class="com.dida.pojo.Person">
<property name="id" value="10"/>
<property name="name" value="dida"/>
</bean>
用户自定义类型的改善
<bean id="userDao" class="xxx.userDaoImpl"/>
<bean id="userService" class="com.dida.service.impl.userServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
2. 基于命名空间p的简化
<bean id="person" class="com.dida.pojo.Person">
<property name="id" value="10"/>
<property name="name" value="dida"/>
</bean>
改为
<bean id="person" class="com.dida.pojo.Person" p:name="dida" p:id="10"/>
<bean id="userService" class="com.dida.service.impl.userServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
改为
<bean id="userService" class="com.dida.service.impl.userServiceImpl" p:userDAO-ref="userDao"/>
构造注入
构造注入:Spring调用构造方法,通过配置文件为成员变量赋值
开发步骤:
- 提供有参构造方法
- 通过Spring配置文件进行配置
<bean id="customer" class="com.dida.pojo.Customer">
<constructor-arg>
<value>dd</value>
</constructor-arg>
<constructor-arg>
<value>123</value>
</constructor-arg>
</bean>
当构造方法重载的时候:
- 如果参数个数不同时,可以通过constructor-arg的个数进行区分;
- 如果参数相同时,可以在<constructor-arg>中指定类型(type);
<constructor-arg type="int">
<value>123</value>
</constructor-arg>
反转控制和依赖注入
控制:对于成员变量赋值的控制权
反转控制:把对于成员变量的赋值的控制权,从代码中反转(转移)到Spring工厂和配置文件中完成,能够充分解耦
底层实现:工厂设计模式
依赖注入:这是Spring的一种编程方式
注入:通过Spring的配置文件为对象(bean,组件)的成员变量赋值
依赖注入:当一个类需要另外一个类的时候,就意味着依赖,一旦出现依赖,就可以把另一个类作为本类的成员变量,最终通过Spring的配置文件进行注入(赋值)
总结
在未来的实战当中,应用set注入的场景会更多,因为构造注入首先由于重载会更加麻烦,同时Spring框架底层也是大量的使用了set注入。