1.IOC概念
IOC控制反转
使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转。通俗的讲就是“将new对象的权利交给Spring,我们从Spring中获取对象使用即可”
Spring实现
Spring提供了一个容器,称为IOC容器,用来充当IoC思想中的“外部”IOC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为Bean(Bean容器)
DI依赖注入
在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入。eg service和dao层的关系
2.IOC流程图
3.IOC入门步骤
步骤一:导入Spring坐标
<dependencies>
<!--导入spring的坐标spring-context,对应版本是5.2.13.RELEASE-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.2</version>
</dependency>
</dependencies>
步骤二:定义Spring管理的类dao&service
//bookdao接口和实现类
public interface BookDao {
public void save();
}
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
//bookService接口和实现类
public interface BookService {
//注意这并未使用DI思想
public void save();
}
public class BookServiceImpl implements BookService {
private BookDao bookDao = new BookDaoImpl();
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
步骤三:创建Spring配置文件,配置应类作为Spring管理的bean对象
(在这个配置中,通过 <bean>
标签定义了一个名为 bookService
的bean,并指定了它的具体实现类为 com.gaohe.service.impl.BookServiceImpl
。当应用程序启动时,Spring 框架会根据这个配置文件中的信息实例化 BookServiceImpl
类,并将其注入到需要依赖的地方。例如,如果在其他类中需要使用 BookService
,可以通过 Spring 框架来获取这个实例,而不需要手动创建它。)
<?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标签:表示配置bean
id属性:表示给bean起名字
class属性:表示给bean定义类型
-->
<bean id="bookService" class="com.xixi.service.impl.BookServiceImpl"></bean>
注意class是impl实现类
</beans>
步骤四:初始化IOC容器,通过容器获取Bean对象
public class Test{
public static void main(String[] args){
//1.创建ioc容器对象,加载spring核心配置文件
ApplicationContext ctx =new ClassPathXmlApplicationContext("applicationContext.xml");
//2.从ioc容器中获取bean对象(BookService对象)
BookService bookService=ctx.getBean("bookService");
//3.调用bean对象(BookService对象)的方法
bookService.save();
}
}
4.DI入门
1)删除使用new的形式创建对象的代码
2)提供依赖对象对应的setter方法
public class BookServiceImpl implements BookService {
// private BookDao bookDao = new BookDaoImpl();
public void save() {
System.out.println("book service save ...");
bookDao.save();
//2.同依赖对象对应的setter方法
public void setBook(BookDao bookDao){
this.bookDao=bookDao;
}
}
3)配置service与dao之间的关系xml
(在这个配置中,除了定义了 bookService
bean 的实现类为BookServiceImpl
外,还使用了 <property>
标签配置了 bookService
与 bookDao
之间的依赖关系。
具体来说:
-
<property>
标签用于配置当前 bean 的属性。 -
name
属性指定了要配置的属性名,这里是bookDao
。 -
ref
属性指定了依赖的 bean 的引用,这里是bookDao
。
通过这样的配置,Spring 框架在实例化 bookService
bean 时会自动将 bookDao
bean 注入到 bookService
中,从而实现了依赖注入。)
<bean id="bookDao" class="com.xixi.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.xixi.service.impl.BookServiceImpl">
<!--配置server与dao的关系
property标签:表示配置当前bean属性
name属性:表示配置哪一个具体的属性
ref属性:表示参照哪一个bean
-->
<property name="bookDao" ref="bookDao"/>
</bean>
4)调用测试
public class App {
public static void main(String[] args) {
//1.创建IoC容器对象,加载spring核心配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//2 从IOC容器中获取Bean对象(BookService对象)
BookService bookService= (BookService)ctx.getBean("bookService");
//3 调用Bean对象(BookService对象)的方法
bookService.save();
}
}
5.Bean
5.1Bean的作用范围配置
5.2Bean实例化
(Bean对象创建方式)
1)构造方法方式(dao实现类)
public class BookDaoImpl implements BookDao {
public BookDaoImpl() {
//默认构造方式-调用构造器
System.out.println("book dao constructor is running ....");
}
public void save() {
System.out.println("book dao save ...");
}
}
2)静态工厂方式
应用场景:在初始化bean钱进行参数项设置;对老系统架构进行兼容时使用
3)实例工厂方式
应用场景:借助工厂类批量加载类;老项目升级时,可将老项目中的bean加载到新工厂中;许多框架底层实现都是基于此,比如springMVC框架,把批量的controller类加载到容器中
//1.实例工厂创建对象
public class UserDaoFactory {
public UserDao getUserDao(){
return new UserDaoImpl();
}
}
//2.使用实例工厂实例化bean
<bean id="userFactory" class="com.xixi.factory.UserDaoFactory"/>
<bean id="userDao" factory-bean="userFactory" factory-method="getUserDao" />
//3.创建FactoryBean对象
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
//代替原始实例工厂中创建对象的方法
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
public Class<?> getObjectType() {
return UserDao.class;
}
}
//4.使用FactoryBean实例化bean
<bean id="userDao" class="com.xixi.factory.UserDaoFactoryBean"/>
5.3Bean的生命周期
public class Student {
private int id;
private String name;
public Student(){
System.out.println("1. 无参构造器实例化");
}
public void init(){
System.out.println("3. init初始化");
}
public void destory (){
System.out.println("5. destory 对象销毁");
}
public int getId() {
System.out.println("4. 对象调用 getId");
return id;
}
public void setId(int id) {
System.out.println("2. set id 赋值");
this.id = id;
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
}
5.4Bean的DI依赖注入
1)set注入
步骤一:在bean中定义引用类型属性并提供可访问的set方法
//service的impl实现类bean
public class BookServiceImpl implements BookService{
private BookDao bookDao;
private String name;
// set方法自行创建
}
步骤二:配置中使用property标签
(第一个name是bookService的bookDao属性,将其与bookDao的另一个bean关联起来)
<bean id="bookService"class="com.xixi.service.impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"/>
<property name="name" ref="zhangsan"/>
</bean>
<bean id="bookDao" class="com.xixi.dao.impl.BookDaoImpl"/>
2)构造器注入
//配置中使用constructor-arg标签
<bean id="bookService" class="com.xixi.service.impl.BookServiceImpl">
<constructor-arg name="bookDao" ref="bookDao"/>
<constructor-arg name="name" ref="lisi"/>
</bean>
<bean id="bookDao" class="com.xixi.dao.impl.BookDaoImpl"/>
3)自动装配
<bean id="bookService" class="com.xixi.service.impl.BookServiceImpl"/>
<bean id="bookDao" class="com.xixi.dao.impl.BookDaoImpl" autowire="byType"/>
自动装配用于引用类型依赖注入,不能对简单类型进行操作使用按类型装配(byType)必须保障容器中相同类型的bean唯一,推荐使用使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
4)集合注入
注入数组类型数据
<property name="array">
<array>
<value>100</value>
<value>200</value>
<value>300</value>
</array>
注入List类型数据
<property name="List">
<array>
<value>100</value>
<value>200</value>
<value>300</value>
</array>
</property>
注入Set类型数据
<property name="set">
<array>
<value>100</value>
<value>200</value>
<value>300</value>
</array>
</property>
注入Map类型数据
<property name="map">
<map>
<entry key="country" value="china"/>
<entry key="province" value="shandong"/>
<entry key="city" value="qingdao"/>
</map>
</property>
注入Properties类型数据
<property name="properties">
<props>
<prop key="country" value="china"></prop>
<prop key="province" value="shandong"></prop>
<prop key="city" value="qingdao"></prop>
</props>
</property>