一,IOC的理论推导(非常重要)
前言:ioc是Spring框架的核心思想,不去理解它就去学习Spring,那是不明智的选择
优点:解耦
原因:再没接触ioc思想之前,为满足客户需求,一般要在service层实例化一个dao层对象,这是为了与service层产生联系,达到参数/数据传递的目的,
但这样耦合度就大大的增加了(因为dao--联系-->service--联系-->servlet),按照项目的高内聚低耦合的思想,这样的方法严重占用了资源,所以ioc出现了,
它将需求实现的控制权(就是实例化对象的控制权)交给了用户,将实例化的过程交给第三方(ioc容器),通过它去与service产生联系,实现需求,(降低了耦合,灵活性更高,是各层间更加独立)
小结:(官方解释)控制反转是通过描述(XML/或注解),并通过第三方去生产或获取特定对象的方式,在Spring中是实现控制反转的是ioc容器,实现方法是依赖注入(Dependency Injecion,DI)
以前,程序是主动创建对象,控制权在程序猿手里
ioc,控制权在客户手里,想创建那个对象,通过ioc容器去创建然后交给项目,因此程序由原来的主动创建变成被动接收,所以被形容为控制反转(ioc)
注意:所谓的ioc对象由Spring来创建,管理,装配
很多人都说DI(依赖注入)是ioc的另一种说法,其实不是的,它只是实现ioc的一种方法,ioc是一种思想,是Spring框架的核心思想
依赖注入:本质就是set方法实现的
底层:放射机制,通过全类名去获得它的属性和方法
扩展:Bean是啥
1、Java面向对象,对象有方法和属性,那么就需要对象实例来调用方法和属性(即实例化);
2、凡是有方法或属性的类都需要实例化,这样才能具象化去使用这些方法和属性;
3、规律:凡是子类及带有方法或属性的类都要加上注册Bean到Spring IoC的注解;
4、把Bean理解为类的代理或代言人(实际上确实是通过反射、代理来实现的),这样它就能代表类拥有该拥有的东西了
5、我们都在微博上@过某某,对方会优先看到这条信息,并给你反馈,那么在Spring中,你标识一个@符号,那么Spring就会来看看,并且从这里拿到一个Bean或者给出一个Bean
二,使用Spring创建对象
配置bean
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!--使用Spring来创建对象,在Spring这些都称为bean--> <!--通过反射机制的全类名去加载类获得那个类所有的属性和方法--> <!--id是对象名,class是全类名--> <bean id="hello" class="com.king.pojo.Hello" > <property name="str" value="Spring"/> </bean> </beans>
扩展:在网站维护期间,与该源代码相比,该配置的好处就是不需要让项目彻底停机就可以改
三,ioc对象创建方式
pojo实体类
注意:当实体类中没有有参构造器时,创建对象时默认走的是无参构造器,(隐式显示),创建对象本身就是通过构造器创建的
package com.king.pojo; public class User { private String name; //无参构造是默认就有的(隐式) public User(){ System.out.println("User的无参构造"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public void show(){ System.out.println("name:"+name); } }
1,利用无参构造器,beans.xml,(利用ioc思想,bi创建方式在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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="com.king.pojo.User"> <property name="name" value="king"/> </bean> </beans>
单元测试
import com.king.pojo.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Mytest { @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); User bean = (User) context.getBean("user"); bean.show(); } }
2,有参构造方式创建对象(三种方式)
2.1下标赋值
<bean id="user" class="com.king.pojo.User"> <!--有参构造创建对象,index是下标,0为第一个位置,value是赋的值--> <constructor-arg index="0" value="龙神"/> </bean>
2.2 传参类型赋值(基本类型直接写,引用类型写全名),不建议使用,不够直观
<bean id="user" class="com.king.pojo.User"> <constructor-arg type="java.lang.String" value="long"/> </bean>
2.3 根据传参名去赋值
<bean id="user" class="com.king.pojo.User"> <constructor-arg name="name" value="cl"/> </bean>
注意:在使用 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");getBean多个相同类时,其实容器在内存中只调用了一个对象
例子: