【SSM - Spring篇02】IOC容器 - 控制反转和依赖注入详解,案例实现(注解方式)
控制反转和依赖注入控制反转(Inversion of Control,IoC)是一个比较抽象的概念,是Spring框架的核心,用来消减计算机程序的耦合问题。依赖注入(Dependency Injection,DI)是IoC的另外一种说法,只是从不同的角度,描述相同的概念。控制反转是一种通过描述(在Spring中可以是XML或注解)并通过第三方去产生或获取特定对象的方式。在Spring中实现控制反转
文章目录
1. 控制反转(IOC)和依赖注入(DI)介绍
控制反转(Inversion of Control,IoC)是一个比较抽象的概念,是Spring框架的核心,用来消减计算机程序的耦合问题。
依赖注入(Dependency Injection,DI)是IoC的另外一种说法,只是从不同的角度,描述相同的概念。
1.1 控制反转IOC(基于反射)
控制反转是一种通过描述(在Spring中可以是XML或注解)并通过第三方去产生或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入。(简单说,就是把创建对象和管理对象的权利交给spring)
- 就是把原来new对象的这种方式转换成了由spring通过反射技术(通过class)创建对象的方式。
- spring创建完的对象放到一个容器中,谁需要就给谁注入进去 - (获取对象并赋值给引用)
new ClassPathXmlApplicationContext(“applicationContext.xml”);
获取核心配置。
1.2 依赖注入DI(赋值基于set方法)
依赖注入是Spring容器将被依赖对象赋值给调用者的成员变量,相当于为调用者注入它所依赖的实例。(本质上就是给对象的属性赋值(set方法),对对象的属性进行赋值)
可以通过bean的property标签进行对对象的赋值。(property标签就是调set方法**)**
property对象的赋值就是调用对象的set方法设置属性。如果让Spring容器管理set赋值,对象一定要有对应的set方法,且名称一致。
property标签,找的是类的属性对应的set方法,本质调set方法,如果对应属性对应set方法不存在,就会报红,找不到
2. SpringIOC
Spring IoC容器的设计主要是基于BeanFactory和ApplicationContext两个接口。我们一般就用第二种的ClassPathXmlApplicationContext
。
2.1 BeanFactory(通过绝对路径)
创建BeanFactory实例时,需要提供XML文件的**绝对路径。**
//创建BeanFactory 实例 -- 通过绝对路径
BeanFactory beanFactory = new XmlBeanFactory(
new FileSystemResource("E:\\SSM\\Spring\\src\\com\\xgf\\ioc\\applicationContext.xml")
2.2 ApplicationContext的创建(通过类路径)【*****主要使用这种方式】
2.2.1 通过ClassPathXmlApplicationContext创建。
ClassPathXmlApplicationContext将从类路径classPath目录(src根目录开始)寻找指定的XML配置文件。
【注意】在Spring中调用方法的名称和路径一定要和对应bean的路径和名称一致,因为IOC是通过反射,调用class文件来获取bean的,而项目有一个target文件夹,它的路径和方法名是和你需要调用的类的路径和方法名一致的。
//类路径
ApplicationContext context =
new ClassPathXmlApplicationContext("com/xgf/ioc/applicationContext.xml");
2.2.2 通过FileSystemXmlApplicationContext创建
FileSystemXmlApplicationContext将从指定文件的绝对路径中寻找XML配置文件,找到并装载完成ApplicationContext的实例化工作
// 绝对路径
ApplicationContext appCon =
new FileSystemXmlApplicationContext("E:\\SSM\\Spring\\src\\com\\xgf\\ioc\\applicationContext.xml");
TestDao tt = (TestDao)appCon.getBean("test");
2.2.3 通过Web服务器实例化ApplicationContext容器
Web服务器实例化ApplicationContext容器时,一般使用基于org.springframework.web.context.ContextLoaderListener的实现方式
此方法需要在web.xml中添加如下代码:
<context-param>
<!-- 加载src目录下的applicationContext.xml文件 -->
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
</param-value>
</context-param>
<!-- 指定以ContextLoaderListener方式启动Spring容器 -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
2.3 scope属性,设置单例多例【**】
单例:内存中只有一个对象,每次获取到该对象的地址值一样。
多例:内存中的每个对象都是一个新的对象,他们的地址值都不同。调用就创建新对象。.
scope="singleton" 单例(默认值,所以调用Spring创建对象默认都是同一个对象)
scope="prototype" 多例
scope="request" 创建的对象放到request域中
scope="session" 创建对象放到session对象
3. DI依赖注入类型
Spring中实现IoC容器的方法是依赖注入,依赖注入的作用是在使用Spring框架创建对象时,动态地将其所依赖的对象(如属性值)注入Bean组件中。
Spring框架的依赖注入通常有两种实现方式:
一种是构造方法注入,另一种是属性setter方法注入。
3.1 构造方法注入(constructor-arg)
Spring框架采用Java的反射机制,通过构造方法完成依赖注入。
constructor-arg给成员变量赋值(调用构造方法注入)
constructor-arg属性 | 描述 |
---|---|
name | 该属性对应bean的成员变量名 |
value | 该属性对应对应name的成员变量的值,可用于赋值 |
bean的constructor-arg 属性,调用bean对象的构造器进行赋值,赋值必须按照构造函数的参数赋值,不能少,用的地方很少。
<!-- 相当于User user = new User(1,"jack",20,new Date()); 调用构造器赋值-->
<bean id="date" class="java.util.Date"/>
<bean id="user" class="com.xgf.bean.User" >
<constructor-arg name="id" value="10"/>
<constructor-arg name="name" value="hello"/>
<constructor-arg name="age" value="20"/>
<constructor-arg name="birthday" ref="date"/>
</bean>
3.2 属性set方法注入【***】(常用)
set方法注入是Spring框架中最主流的注入方式,它利用Java Bean规范所定义的set方法来完成注入,灵活且可读性高。set方法注入,Spring框架也是使用Java的反射机制实现的。
通过bean的property标签- 给成员变量赋值(调用set方法注入)
property属性 | 描述 |
---|---|
name | 该属性对应bean的成员变量名 |
value | 该属性对应对应name的成员变量的值,可用于赋值 |
property调用set方法赋值
<bean id="user" class="com.xgf.bean.User" >
<!-- 相当于user.setId(10) -->
<property name="id" value="10"/>
<!-- 相当于user.setName(rose) -->
<property name="name" value="rose"/>
<property name="age" value="20"/>
</bean>
property标签,找的是类的属性对应的set方法,在idea中,如果对应bean对应的set方法不存在,就会报红,提示找不到错误。(就是有对应的属性存在,但是没有对应属性的set方法,就不能通过property赋值)
4. 案例实现调用set方法注入,模拟IOC容器的注入(通过ClassPathXmlApplicationContext方式创建ApplicationContext)
步骤:
1.创建javabean类
2、创建Controller类将Controller托管给spring,让spring创建其对象
3.创建service接口实现类serviceImpl将serviceImpl托管给spring,让spring创建其对象
4、创建Dao接口实现类DaoImpl将DaoImpl托管给spring,让spring创建其对象
5、在Test中测试setter方法注入
简介需要用到的注解:
@Component //所有类上都可以使用
@Repository //Dao层用这个
@Service //Service层用这个
@Controller() //Controller层用这个
//上面四个注解,是用来标识为bean对象,Spring容器扫描的时候能够识别加载
@Autowired //自动装载,就是从Spring容器中找到类型相同的bean赋值给它
// 比如 private UserService userService;
// 相当于执行了实例化 private UserService userService = new UserServiceImpl();
环境准备:在pom.xml中引入spring的dependency
<!--spring 核心容器-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
4.1 创建测试类TestIOC
(Spring/src/main/java/com/xgf/ioc/Test/TestIOC.java)
/*
* 测试IOC依赖注入 - 通过setter方法注入
* */
public class TestIOC {
public static void main(String[] args) {
//注解进行配置,实例化ApplicationContext容器 通过ClassPathXmlApplicationContext方式实例化ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("com/xgf/ioc/applicationContext.xml");
//通过getBean方法从ApplicationContext容器当中获取User对象
UserController userContrller = (UserController)context.getBean("userController");
//调用User的name参数构造器测试
userContrller.saveUser(new User("GF_浪夏一学"));
}
}
4.2 创建User类(Spring/src/main/java/com/xgf/ioc/bean/User.java)
import java.util.HashMap;
import java.util.List;
import java.util.Set;
public class User {
private String name;
public User() {
System.out.println("调用User的无参构造器");
}
public User(String name) {
System.out.println("调用User的name参数构造器");
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
4.3 在resources下创建ApplicationContext.xml配置文件
(Spring/src/main/resources/com/xgf/ioc/applicationContext.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!--suppress SpringFacetInspection -->
<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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置注解扫描 扫描com.xgf.ioc下的所有文件 -->
<context:component-scan base-package="com.xgf.ioc"/>
<!-- 也可以单独配置bean,指定加入容器中的bean -->
<!-- <bean id="user" class="com.xgf.bean.User"></bean> -->
</beans>
4.4 创建Controller
(Spring/src/main/java/com/xgf/ioc/controller/UserController.java)
/*
@Controller注解 该注解用于标注一个控制器组件类
容器一启动就会实例化 创建好之后以类名首字母小写放到容器中
UserController 启动容器之后 创建好之后 变成---> key= userController value=new UserController();
* */
@Controller
public class UserController {
/*
@Autowired注解 按照类型进行匹配 - 自动装载
该注解可以对类成员变量、方法及构造方法进行标注,完成自动装配的工作。
通过 @Autowired的使用来消除setter 和getter方法。默认按照Bean的类型进行装配。
*/
@Autowired
private UserService userService;// 相当于执行了实例化 private UserService userService = new UserServiceImpl();
//调用service的方法saveUser
public void saveUser(User user){
userService.saveUser(user);
}
}
4.5. 创建Service
(Spring/src/main/java/com/xgf/ioc/service/UserService.java)
public interface UserService {
void saveUser(User user);
}
/*
@Service
该注解用于标注一个业务逻辑组件类(Service层),其功能与@Component()相同。
value是默认bean的id
容器加载后会实例化,创建UserService对象
*/
@Service(value="userService")
public class UserServiceImpl implements UserService{
@Autowired
private UserDao userDao;
@Override
public void saveUser(User user) {
userDao.saveUser(user);
}
}
4.6 创建dao
(Spring/src/main/java/com/xgf/ioc/dao/UserDao.java)
public interface UserDao {
void saveUser(User user);
}
/*
@Repository
该注解用于将数据访问层(DAO)的类标识为Bean,即注解数据访问层Bean,其功能与@Component()相同。
容器加载就会被实例化
*/
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void saveUser(User user) {
System.out.println("调用dao层userDao的saveUser方法,保存用户:"+user.getName());
}
}
4.7 运行结果(实现注入成功)
通过创建User对象,调用Controller,通过spring的 @Autowired 注解自动装载service(通过类型找spring容器对应的bean),然后在service中自动装载dao,最后实现注入。@Autowired注解就相当于从Spring容器中通过类型,实例化了当前对象,可以直接调用它的方法。
@Autowired
private UserService userService;
// 相当于执行了实例化 private UserService userService = new UserServiceImpl();
关于注解,交给下一篇来解释啦哈哈哈。
更多推荐
所有评论(0)