SpringIOC纯配置文件
Spring通过一种称作控制反转IOC的技术促进了低耦合,达到当系统一旦出现新的需求之后,尽量少去改动原有的Java类,而是去改配置文件的效果。
控制反转意味着在系统开发的过程中,类将交由容器器控制,而不是在类的内部去控制,类与类之间的关系也交由容器来处理,当一个类需要调用另一个类时,只要调用另一个类在容器中注册的名字就可以得到这个类的实例。
而类的对象是由spring通过反射机制创建的。
控制反转=创建对象
依赖注入=给对象中的属性赋值
自动注入=spring容器帮你给对象中属性赋值
一、类的注册与调用
首先创建service层和dao层,为了简化操作,dao层不去操作数据,而是默认输出一个操作成功的值。
- StudentDao
public class StudentDao {
//拟保存学生信息
public void insertStudent(){
System.out.println("学生信息保存成功");
}
}
- StudentService
public class StudentService {
private StudentDao studentDao;
public void insertStudent(){
studentDao.insertStudent();
}
}
- spring.xml
其中id为注册进spring容器中的对象名,就是这个对象在spring容器中挂什么名字
name为对象对应的全限定类名。
id是唯一的,而且容器中的对象默认是单例的。
<?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容器-->
<bean id="studentDao" class="com.lgy.dao.StudentDao" />
<bean id="studentService" class="com.lgy.service.StudentService"/>
</beans>
- TestIOC
可以视ApplicationContext为Spring容器,ClassPathXmlApplicationContext类顾名思义就是为了引入spring配置文件,进而创建出容器对象。
通过容器对象getBeanDefinitionNames就可以得到容器中对象的注册名。
容器中注册了的对象会在运行时全部通过反射机制调用其无参构造来进行初始化。
public class TestIOC {
//引入配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
@Test
public void testFirst(){
//查看spring容器中都有哪些类注册
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
//打印容器中的注册名
System.out.println(Arrays.toString(beanDefinitionNames));
//第一个参数时spring容器中注册时用的名称,第二个参数是注册类,这样就可以创建一个对应类型的引用
StudentDao studentDao = applicationContext.getBean("studentDao", StudentDao.class);
studentDao.insertStudent();
}
}
- 执行结果
二、属性的注入
属性的注入就是给类中的属性赋值,例如上例中如果我们调用studentService中的insertStudent()方法,就会出现空指针异常。
- TestIOC
@Test
public void testAutowied(){
StudentService studentService = applicationContext.getBean("studentService", StudentService.class);
studentService.insertStudent();
}
这是因为spring并没有给studentDao赋值,也就是没有给studentDao注入值。
那么属性值改怎么注入呢?
可以通过set注入和构造器注入。
set注入中set方法是必不可少的。
- StudentService
public class StudentService {
private StudentDao studentDao;
public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
}
public void insertStudent(){
studentDao.insertStudent();
}
}
- spring.xml
通过properties就能完成对类中属性的赋值操作。
<?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容器-->
<bean id="studentDao" class="com.lgy.dao.StudentDao" />
<bean id="studentService" class="com.lgy.service.StudentService">
<!--name表示类中的属性名,ref对应着spring容器中的注册名-->
<property name="studentDao" ref="studentDao"/>
</bean>
</beans>
整个流程
三、自动注入
属性的自动注入就是我们不需要去写properties标签了,让spring容器自己去寻思着选哪个对象来注入。
1、byType
byType为通过类型来实现自动注入。
创建几个实体类,其中orders类中存在其他三个类的属性
- orders.java
//订单类:每个订单中必须包含一中食物,一种衣服和一种电器
public class Orders {
private Food food;
private Clothes clothes;
private Electric electric;
public void setFood(Food food) {
this.food = food;
}
public void setClothes(Clothes clothes) {
this.clothes = clothes;
}
public void setElectric(Electric electric) {
this.electric = electric;
}
@Override
public String toString() {
return "Orders{" +
"food=" + food +
", clothes=" + clothes +
", electric=" + electric +
'}';
}
}
- Food.java
public class Food {
private String name;
public void setName(String name) {
this.name = name;
}
}
- Clothes.java
public class Clothes {
private String name;
public void setName(String name) {
this.name = name;
}
}
- Electric.java
public class Electric {
private String name;
public void setName(String name) {
this.name = name;
}
}
- 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">
<!--把刚刚创建好的类注册给spring容器-->
<bean id="studentDao" class="com.lgy.dao.StudentDao" />
<bean id="studentService" class="com.lgy.service.StudentService"/>
<!--注入实体类-->
<bean id="clothes" class="com.lgy.entity.Clothes">
<property name="name" value="上衣" />
</bean>
<bean id="food" class="com.lgy.entity.Food">
<property name="name" value="辣条" />
</bean>
<bean id="electric" class="com.lgy.entity.Electric">
<property name="name" value="手机" />
</bean>
<bean id="orders" class="com.lgy.entity.Orders" autowire="byName" />
</beans>
如果不使用自动注入,应该这么写
<bean id="orders" class="com.lgy.entity.Orders">
<property name="electric" ref="electric"/>
<property name="clothes" ref="clothes"/>
<property name="food" ref="food"/>
</bean>
当spring容器中存在两个相同类型的注册对象,再使用byType自动注入会报错,因为spring也不知道该使用哪个对象来实现注入操作。
2、byName
byName是根据名称来实现属性值的自动注入,用过解析属性对应的set方法的set之后的值,再将首字母小写,去spring容器中搜寻该注册名实现注入,比如说setFood,就会根据food去spring容器中来找对应的名称实现注入。
写法只需要将byType改为byName即可。
<bean id="orders" class="com.lgy.entity.Orders" autowire="byName" />
- 执行结果
@Test
public void testByType(){
//拿到orders的引用
Orders orders = applicationContext.getBean("orders", Orders.class);
System.out.println(orders);
}
标签:容器,依赖,name,spring,void,studentDao,Spring,public,反转
From: https://www.cnblogs.com/lgyy/p/16871724.html