Sping5---IOC理论推导再一步步深入
1、 IOC理论推导
原来的业务步骤:
1.UserDao接口
package edu.xalead.dao; public interface UserDao { void getUser(); }
2.UserDaoImpl实现类
package edu.xalead.dao; public class UserDaoImp implements UserDao { public void getUser(){ System.out.println("默认获取用户的数据"); } } package edu.xalead.dao; public class UserDaoMySqlImp implements UserDao { public void getUser() { System.out.println("获取MySQL数据"); } } package edu.xalead.dao; public class UserDaoOracleImp implements UserDao { public void getUser() { System.out.println("获取Oracle数据"); } }
3.UserService业务接口
package edu.xalead.service; public interface UserService { void getUser(); }
4.UserServiceImpl业务实现类
package edu.xalead.service; import edu.xalead.dao.UserDao; import edu.xalead.dao.UserDaoImp; import edu.xalead.dao.UserDaoMySqlImp; import edu.xalead.dao.UserDaoOracleImp; public class UserServiceImp implements UserService { //有新的业务我们就要改代码去new一个让用户调用 private UserDao userDao = new UserDaoImp(); // private UserDao userDao = new UserDaoMySqlImp(); // private UserDao userDao = new UserDaoOracleImp(); public void getUser() { userDao.getUser(); } }
测试用户:
@Test public void test1(){ UserServiceImp userServiceImp = new UserServiceImp(); userServiceImp.getUser(); }
比如用户又要访问sqlserver
我们需要加一个实现类
package edu.xalead.dao; public class UserDaoSqlserverImpl implements UserDao{ public void getUser() { System.out.println("获取MySQL数据"); } }
并且修改源码再new一个UserDaoSqlserverImpl:
private UserDao userDao = new UserDaoSqlserverImpl();
总结:在我们之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改源代码!如果程序代码量十分大,修改一次的成本代价十分昂贵!
现在:
我们使用一个Set接口实现,已经发生了革命性的变化!
private UserDao userDao; //利用set进行动态实现值的注入! public void setUserDao(UserDao userDao){ this.userDao = userDao; }
@Test public void test1(){ UserServiceImp userServiceImp = new UserServiceImp(); userServiceImp.setUserDao(new UserDaoImp()); userServiceImp.getUser(); }
- 之前,程序是主动创建对象!控制权在程序员手上!
- 使用了set注入后,程序不再具有主动性,而是变成了被动的接收对象!
这种思想,从本质上解决了问题,我们程序员不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专注在业务的实现上。这是IOC的原型!
IOC本质
控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法。没有IOC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IOC容器,其实现方式是依赖注入(Dependency Injection,DI)。
2、 IOC创建对象的方式(DI中的构造器注入)
-
使用无参构造创建对象,默认方式!
-
假设我们要使用有参构造创建对象。
1.下标赋值。
<!--第一种,下标赋值!--> <bean id="user" class="com.kuang.pojo.User"> <constructor-arg index="0" value="李四" /> </bean>
2.类型赋值。
<!--第二种,通过类型创建,不建议使用,重复类型难以分辨--> <bean id="user" class="com.kuang.pojo.User"> <constructor-arg type="java.lang.String" value="张三" /> </bean>
3.参数名赋值。
<!--第三种,直接通过参数名来设置--> <bean id="user" class="com.kuang.pojo.User"> <constructor-arg name="name" value="王五" /> </bean>
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了!
3、 依赖注入
3.1 构造器注入
之前已经介绍过了
3.2 Set方式注入【重点】
- 依赖注入:本质Set注入! 依赖:bean对象的创建依赖于容器!
- 注入:bean对象中的所有属性,由容器来注入!
【环境搭建】
-
复杂类型
public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
-
真实测试对象
public class Student { private String name; private Address address; private String[] books; private List<String> hobbies; private Map<String,String> card; private Set<String> games; private String wife; private Properties info; }
[ol]applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="student" class="com.kuang.pojo.Student"> <!--第一种,普通值注入--> <property name="name" value="张三"/> </bean> </beans>
-
测试类
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.getName()); } }
完善注入:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="address" class="com.kuang.pojo.Address"/> <bean id="student" class="com.kuang.pojo.Student"> <!--第一种,普通值注入,value--> <property name="name" value="憨批"/> <!--第二种,Bean注入,ref--> <property name="address" ref="address"/> <!--数组注入--> <property name="books"> <array> <value>红楼梦</value> <value>西游记</value> <value>水浒传</value> <value>三国演义</value> </array> </property> <!--List注入--> <property name="hobbies"> <list> <value>听歌</value> <value>敲代码</value> <value>看电影</value> </list> </property> <!--Map--> <property name="card"> <map> <entry key="身份证" value="1555555555"/> <entry key="银行卡" value="5555555555"/> </map> </property> <!--Set--> <property name="games"> <set> <value>lol</value> <value>wow</value> </set> </property> <!--null--> <property name="wife"> <null/> </property> <!--Properties--> <property name="info"> <props> <prop key="driver">com.mysql.jdbc.Driver</prop> <prop key="url">jdbc:mysql://localhost:3306/news</prop> <prop key="root">root</prop> <prop key="password">123456</prop> </props> </property> </bean> </beans>
3.3 拓展方式注入(其他)
我们可以使用c和p命令空间进行注入:
使用:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--p命名空间注入,可以直接注入属性的值:property--> <bean id="user" class="com.kuang.pojo.User" p:name="李四" p:age="18"/> <!--c命名空间注入,通过构造器注入:construct-args--> <bean id="user2" class="com.kuang.pojo.User" c:age="18" c:name="张三"/> </beans>
测试:
@Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml"); User user = context.getBean("user2", User.class); System.out.println(user.toString()); }
注意点:p和c命名空间不能直接使用,需要导入xml约束!
xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
欢迎访问我的个人博客看完整版Spring5:http://www.ayjup.cn
- 点赞
- 收藏
- 分享
- 文章举报
- Castle的IoC容器深入分析
- Android LayoutInflater原理分析,带你一步步深入了解View(一)
- Android视图绘制流程完全解析,带你一步步深入了解View(二)
- 读完spring源码深入后浅出系列之什么是ioc
- Android视图绘制流程完全解析,带你一步步深入了解View(二)
- Android自定义View的实现方法,带你一步步深入了解View(四)
- Android视图状态及重绘流程分析,带你一步步深入了解View(三)
- 【SSH进阶之路】Spring的IOC逐层深入——依赖注入的两种实现类型
- Java:一步步带你深入了解神秘的Java反射机制
- [置顶] 《机器学习实战》学习笔记(四)之Logistic(上)基础理论及算法推导、线性回归,梯度下降算法
- XGBoost理论相关推导
- 深入理解Spring--动手实现一个简单的SpringIOC容器
- EM 算法理论推导
- 【SSH进阶之路】Spring的IOC逐层深入——为什么要使用IOC[实例讲解](二)
- Spring IOC&AOP 深入剖析(史上最全,没有之一)
- 卡尔曼理论学习及公示推导
- Android自定义View的实现方法,带你一步步深入了解View
- 深入理解IOC控制反转及应用实例
- Spring Framework(2):深入理解IoC
- BP(全连接网络)正向反向传播理论推导