发布于2021-06-12 15:35 阅读(701) 评论(0) 点赞(24) 收藏(1)
IOC是Inversion of Control的缩写,直译为控制反转。简单的说就是当我们需要一个对象时,不再由我们自己手动去创建,而是让框架代替我们去创建,把控制权交给框架,也就是控制反转。
IOC又可以叫DI(Dependency Injection),直译为依赖注入。将我们需要依赖的的对象由框架自动注入。
引入IOC最主要的目的就是为了实现对象间的解耦。
参考网址:https://www.cnblogs.com/DebugLZQ/archive/2013/06/05/3107957.html
在Spring中,构成应用程序主干并由Spring IoC容器管理的对象称为bean。bean是一个由Spring IOC容器实例化、组装和管理的对象。
虽说bean在Spring中指的是对象,但JavaBean却是一种类,两者非常容易混淆,所以我通常还是习惯于将由IoC容器管理的对象的类称为bean
参考网址:https://www.cnblogs.com/wwct/p/12742347.html
新建一个maven项目
导入spring-context依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
新建一个UserService
类,内容如下
public class UserService {
public void test(){
System.out.println("我是userService的test方法");
}
}
新建一个配置文件夹resources
,并在里面新建一个配置文件spring.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: bean对象的唯一标识
class: bean对象对应的全路径
-->
<bean id="userService" class="org.example.UserService"></bean>
<!-- more bean definitions go here -->
</beans>
新建一个启动类starter
,内容如下:
public class Starter {
public static void main(String[] args) {
// 创建Spring的上下文环境(Spring IOC 容器),并负责实例化,配置和组装Bean
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
// 创建bean,传入bean的id
UserService userService = (UserService) ac.getBean("userService");
userService.test();
}
}
运行程序,可以查看到控制台输出我是userService的test方法
。
通过这个简单的示例程序,我们可以看到,我们没有new一个UserService
对象,但却拿到该对象,说明这个对象是由spring帮我们实例化的,这就是IOC。
主要有两种方式,一种通过相对路径,一种通过绝对路径,但一般我们都使用相对路径。这两种方式都支持一次性写入多个配置文件。
相对路径:
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");// 单个
ApplicationContext ac = new ClassPathXmlApplicationContext("spring01.xml", "spring02.xml");// 多个
绝对路径:
ApplicationContext ac = new FileSystemXmlApplicationContext("C:/.../.../src/main/resources/spring.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">
<!-- 导入配置文件 -->
<import resource="spring01.xml"/>
<import resource="spring02.xml"/>
</beans>
构造器实例化:就是我们上面的例子中的,默认是通过无参构造器进行实例化,比较常用,例如:
<bean id="userService" class="org.example.UserService"/>
静态工厂实例化:通过工厂方法进行实例化,需要先写一个静态工厂,并配置factory-method
,例如:
public class MyFactory {
/*定义对应的工厂方法,返回实例化对象*/
public static UserService createUserService(){
return new UserService();
}
}
<!--
静态工厂实例化
class: 指定静态工厂类
factory-method: 对应的实例化方法
-->
<bean id="userService" class="org.example.MyFactory" factory-method="createUserService"/>
实例化工厂实例化:工厂方法为非静态的,且需要先将实例化工厂实例化为bean,并配置factory-method
和factory-bean
,例如:
public class MyFactory {
/*定义对应的工厂方法,返回实例化对象*/
public UserService createUserService(){
return new UserService();
}
}
<bean id="myFactory" class="org.example.MyFactory"/>
<bean id="userService" factory-bean="myFactory" factory-method="createUserService"/>
即通过配置文件进行依赖注入,常用的set方法注入,构造器注入两种。首先我们定义一个UserDAO
,其被UserService
依赖,如下
public class UserDAO {
public void test(){
System.out.println("我是UserDAO的test");
}
}
这种方法需要提供依赖的set方法,例如
public class UserService {
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
private UserDAO userDAO;
public void test(){
System.out.println("我是userService的test方法");
userDAO.test();
}
}
配置文件通过需要property
标签,对依赖进行手动注入,例如
<!-- 依赖的bean定义 -->
<bean id="userDAO" class="org.example.UserDAO"/>
<!-- 通过set方法,手动注入依赖 -->
<bean id="userService" class="org.example.UserService">
<!-- name:属性名,ref:对应的bean -->
<property name="userDAO" ref="userDAO"/>
</bean>
若需要注入int
或String
等类型的依赖,可以将ref
属性换成value
属性,其他一样。
需要提供对应的带参构造器,例如
public class UserService {
private UserDAO userDAO;
public UserService(UserDAO userDAO) {
this.userDAO = userDAO;
}
public void test(){
System.out.println("我是userService的test方法");
userDAO.test();
}
}
<!-- 依赖的bean定义 -->
<bean id="userDAO" class="org.example.UserDAO"/>
<!-- 通过set方法,手动装配依赖 -->
<bean id="userService" class="org.example.UserService">
<!--name:构造器中的参数名,ref:对应的bean -->
<constructor-arg name="userDAO" ref="userDAO"/>
</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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启自动装配 -->
<context:annotation-config/>
<bean id="userDAO" class="org.example.UserDAO"/>
<bean id="userService" class="org.example.UserService"/>
</beans>
实现自动注入主要有两个注解:Resource
和Autowired
,将他们注解在需要注入的bean上即可,也可以注解在bean的set方法上。
id
查找,属性名最好与bean标签id
属性值相等id
未找到,则会根据类型(Class)查找name
属性,name
属性值必须与bean标签的id属性值保持一致name
属性指定id
public class UserService {
// @Resource(name = "userDAO")
@Resource
private UserDAO userDAO;
public void test(){
System.out.println("我是userService的test方法");
userDAO.test();
}
}
Qualifie
注解结合使用,通过value
属性值查找bean对象,value
属性值必须要设置,且值要与bean标签的id
属性值对应public class UserService {
@Autowired
@Qualifier(value = "userDAO")
private UserDAO userDAO;
public void test(){
System.out.println("我是userService的test方法");
userDAO.test();
}
}
实际的开发中,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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启自动装配 -->
<context:annotation-config/>
<!-- 开启扫描器 -->
<context:component-scan base-package="org.example"/>
</beans>
然后,我们只需要在包中的类前加上对应的注解,即可自动扫描进容器,主要有以下四个注解
Repository
:用于DAO层Service
:用于服务层Controller
:用于控制层Component
:用于任意类,如工具类等@Repository
public class UserDAO {
public void test(){
System.out.println("我是UserDAO的test");
}
}
主要分别为两种,单例作用域和原型作用域,默认是单例作用域。
单例(singleton)作用域:
其中,lazy-init
是懒加载,当lazy-init
为true
时,当程序调用时才会去实例化该bean对象,默认为false
所有的bean对象都是单例,因为是默认配置,所以不需要写啥。
原型(prototype)作用域:当每次使用时,都会创建一个新的bean对象,不会缓存。需要配置scope="prototype"
,例如
<bean id="userService" class="org.example.UserService" scope="prototype"/>
主要分为四个阶段:
定义:在配置文件中定义bean标签,设置对应的id等属性
创建:在Spring容器中,默认在启动时就会创建所有的bean对象,除非lazy-init="true"
。若在创建时需要执行一些操作,可以在bean标签中设置init-method
为初始化函数,例如:
<bean id="userService" class="org.example.UserService" init-method="init"/>
使用:使用getBean
获取bean对象进行使用
销毁:在bean中设置destroy-method
为销毁函数,并通过AbstractApplicationContext
对象,调用其close
方法销毁bean(若不使用close
方法,在项目结束时也不会销毁bean),例如
<bean id="userService" class="org.example.UserService" destroy-method="destroy"/>
// 创建Spring的上下文环境(Spring IOC 容器),并负责实例化,配置和组装Bean
AbstractApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
// 创建bean对象,传入bean对象的id
UserService userService = (UserService) ac.getBean("userService");
userService.test();
// 销毁bean对象
ac.close();
作者:小胖子爱java
链接:http://www.javaheidong.com/blog/article/222553/5cc1b71e3558f01df96a/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!