理解概念比死记硬背更有效:Spring框架的IOC设计思想+Spring的Bean管理
Posted Lotus_dong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解概念比死记硬背更有效:Spring框架的IOC设计思想+Spring的Bean管理相关的知识,希望对你有一定的参考价值。
文章目录
Spring框架
IOC(控制反转)
IOC:即Inverse of Control,控制反转是一种设计思想,就是将原本在程序中手动创建对象的控制权交给Spring框架来管理。 它的作用是降低对象间的耦合度,底层实现依靠解析xml文件或扫描注解标签+工厂模式+反射机制。
IOC容器具有依赖注入功能,负责对象的实例化、对象初始化、对象之间依赖关系配置、对象的销毁,对外提供对象的查找等操作,对象的整个生命周期都由容器来控制。我们需要使用的对象不需要通过new一个实例的方法去创建,而是由IOC直接帮我们组装好,需要时从IOC容器中获取即可。
理解两个概念:正控即由我们自己去创建要使用的某个对象;反控即直接从Spring容器中取得需要使用的对象,不关心对象的创建过程,也就把创建对象的控制权反转给了Spring框架。
一个简单的例子大家看一下
1.先建立一个实体类:
public class User {
private String name;
private Integer age;
public User() {
System.out.println("User类的无参构造方法已创建!!!");
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public void work() {
System.out.println(this.name+"今年"+this.age+"岁");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
2.我们先在Spring的配置文件中配置java类:
<?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">
<!--将java中的类交给Spring统一管理,由Spring容器生成对象-->
<bean id="user" class="com.cwd.spring1pro.bean.User"></bean>
</beans>
3.在使用中通过Spring框架直接获取对象
@Test
public void test1() {
/*IOC控制反转:在程序中不需要我们去new对象,由Spring容器创建并管理*/
/*读取spring的相关xml文件,加载spring配置文件,启动Spring框架(Spring容器)*/
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
User user = (User) applicationContext.getBean("user");
System.out.println(user);
}
Spring框架的Bean管理
Spring中的bean指的是由Spring框架生成并管理的对象。Spring底层的实现依靠解析xml文件或扫描注解标签+工厂模式+反射机制。那我们在对java类(Bean)的管理中也需要对其进行配置,具体配置方式要么是配置xml文件,要么是配置注解标签。
基于xml配置方式
使用基于xml的配置方式来进行Bean管理,我们通常使用bean标签,
<!--将java中的类交给Spring统一管理,由Spring容器生成对象-->
<bean id="user" class="com.cwd.spring1pro.bean.User"></bean>
bean标签的常用属性:
(1)id=“生成对象的名称”
(2)class=“java类的全类名”
(3)name=“生成对象的名称” ,可以给多个名称
<bean id="user" class="com.cwd.spring1pro.bean.User" name="user1,user2" ></bean>
(4)scope=“作用域”,这里主要说一下scope的取值
- singleton(默认):单例的,Spring框架在它的容器中只创建了一个实例,区分单例和单例模式,单例模式指的是类中构造方法私有。
<bean id="user" scope="singleton" class="com.cwd.spring1pro.bean.User" name="user1,user2" ></bean>
测试:
@Test
public void test3() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
User user = (User) applicationContext.getBean("user");
System.out.println(user);
User user1 = (User) applicationContext.getBean("user1");
System.out.println(user1);
User user2 = (User) applicationContext.getBean("user2");
System.out.println(user2);
}
- prototype:原型的(多例的),每一次获得对象(getBean)时Spring容器才会创建对象。
<bean id="user" scope="prototype" class="com.cwd.spring1pro.bean.User" name="user1,user2" ></bean>
测试:还是上面的测试代码
- 还有其它的作用域取值这里就不进行展示了,如下图。
依赖注入
Spring框架创建对象对象叫做控制反转,在创建对象时我们为创建的对象赋值我们就叫做依赖注入,就是将对象依赖属性(简单值,集合,对象)通过配置设置给该对象。它们两个是相互依存的关系。这里的内容比较简单,但也比较多,我们这里只做一些简单演示,详细内容大家到Spring核心技术网站看。
1.实体类set方法注入
首先我们需要在实体类中对属性进行set方法的重写,这是实现set方法注入的前提。
(1)简单值注入。
使用property属性标签注入,name表示实体类中的属性,value表示给属性注入的值。
<bean id="user" class="com.cwd.spring1pro.bean.User">
<property name="name" value="Tom"></property>
<property name="age" value="22"></property>
</bean>
(2)集合注入
这里我们只以List集合和Map集合为例。List集合直接使用list标签和value标签赋值,Map集合需要使用map标签和entry标签添加键值对赋值。
<bean id="user" class="com.cwd.spring1pro.bean.User">
<property name="name" value="Tom"></property>
<property name="age" value="22"></property>
<property name="list">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
<property name="map">
<map>
<entry key="k1" value="v1"/>
<entry key="k2" value="v2"/>
<entry key="k3" value="v3"/>
</map>
</property>
</bean>
(3)对象注入
- 创建实体类userDao
public class UserDao {
public void saveUser(){
System.out.println("保存User");
}
}
- 创建一个引用实体类的实体类userService
public class UserService {
private UserDao userDao;
public void UserSave() {
userDao.saveUser();
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
- 在spring.xml文件中进行配置注入
对象注入我们使用ref属性,它引用的是被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">
<!--Spring管理了UserDao-->
<bean id="userDao" class="com.cwd.spring2pro.dao.UserDao"></bean>
<!--Spring管理UserService-->
<bean id="userService" class="com.cwd.spring2pro.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
2.构造方法注入
需要在实体类中添加有参的构造方法,建议大家把无参的构造方法也写上。java代码会根据在spring.xml文件中配置的参数个数选择不同的构造方法赋值。
(1)简单值注入
- 实体类中的构造方法
public User(String name, Integer age) {
this.name = name;
this.age = age;
System.out.println("User类的有参构造方法1!!!");
}
- spring.xml文件中的配置
使用constructor-arg标签进行注入,name和value的作用和property中的作用一样。
<!--
通过构造方法注入值,通过参数值数量选择不同的构造方法
-->
<bean id="user" class="com.cwd.spring1pro.bean.User">
<constructor-arg name="name" value="jim"></constructor-arg>
<constructor-arg name="age" value="20"></constructor-arg>
</bean>
也可以使用constructor-arg标签中的index属性注入,根据不同的参数位置进行注入。
<bean id="user" class="com.cwd.spring1pro.bean.User">
<constructor-arg index="0" value="tom"/>
<constructor-arg index="1" value="10"/>
</bean>
(2)集合注入
我们还是以List集合和Map集合为例,基本的使用方法和property一致。
<bean id="user" class="com.cwd.spring1pro.bean.User">
<constructor-arg name="name" value="jim"/>
<constructor-arg name="age" value="22"/>
<constructor-arg name="list">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</constructor-arg>
<constructor-arg name="map">
<map>
<entry key="k1" value="v1"/>
<entry key="k2" value="v2"/>
<entry key="k3" value="v3"/>
</map>
</constructor-arg>
</bean>
基于注解方式实现
我们可以在Spring.xml文件通过配置实现对java类的bean管理和依赖注入,同样的,我们也可以使用注解的方式完成这一步骤。在此之前,我们需要做一些准备工作:首先,我们需要导入注解需要的jar包,注解功能封装在AOP包中,因此导入Spring.aop.jar包即可,其次就是要在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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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">
<!--开启Spring注解扫描,需要注意context的约束,完善beans标签的属性-->
<context:component-scan base-package="需要扫描的java类的包名"> </context:component-scan>
</beans>
不同的java类我们通过不同的注解标签进行注解,一般我们按不同的层(bean,dao,service)进行划分,这并不是说每一层的注解标签只能注解本层的java类,只是为了后续的扩展功能。
(1)bean层,普通的java类——Component
@Component(value = “user”) 等同于我们在xml文件中配置bean标签使用id和class属性
@Component(value = "user")
//等同于<bean id = "user" class = "com.cwd.spring3pro.demo1.bean.User">
@Scope(value = "prototype")
public class User {
private String name;
private Integer age;
public User() {
System.out.println("User类的无参构造方法已创建!!!");
}
public void work() {
System.out.println(this.name+"今年"+this.age+"岁");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
(2)dao层,数据持久层——Respository
@Repository(value = “userDao”)
@Repository(value = "userDao")
public class UserDao {
public void saveUser(){
System.out.println("保存User");
}
}
(3)service层
@Service(value=“userService”)
@Service(value = "userService")
public class UserService {
/*
这里需要注入
*/
private UserDao userDao;
public void UserSave() {
userDao.saveUser();
}
}
(4)其它标签——用作弥补配置xml文件中标签的各种属性
作用域:@Scope
@Scope(value = "prototype") 原型
@Scope(value = "singleton") 单例
依赖注入
这里的依赖注入主要分为两种:一种是按照属性的类型自动注入,另一种是匹配为java类的配置的id值。
byType
@Autowired 自动注入,按照属性的类型自动注入
@Service(value = "userService")
public class UserService {
@Autowired//byType 根据属性的类型匹配查询
private UserDao userDao;
}
@Resource JDK自带的注解方式
@Service(value = "userService")
public class UserService {
@Resource
private UserDao userDao;
}
byName
依靠@Qualifier,需要联合使用自动注解方式(@Autowired或@Resource),@Qualifier的value属性值用于指定要匹配的Bean的id值。
@Service(value = "userService")
public class UserService {
@Autowired
@Qualifier(value = "userDao") //byName 根据对象名称查找 bean的id
private UserDao userDao;
}
@Service(value = "userService")
public class UserService {
@Resource
@Qualifier(value = "userDao")
private UserDao userDao;
}
xml和注解方式
以上是关于理解概念比死记硬背更有效:Spring框架的IOC设计思想+Spring的Bean管理的主要内容,如果未能解决你的问题,请参考以下文章