作者简介:大家好,我是五度鱼,一个普通的Java领域博主,不停输出Java技术博客和干货。
座右铭:锲而不舍,金石可镂。
个人主页:五度鱼学Java的主页
前言
这几天学了Spring6
,感觉到了Spring
的强大和便捷。其中的IOC
设计原则对对象的处理真的是达到了出神入化的地步,省去了不停的创建对象的过程。写此篇文章是为了总结一下IOC
的四种属性注入方式,也是为了以后可以翻看,每日温习一遍,孔子说过:“温故而知新,可以为师矣”。各位朋友们在浏览此篇博客时可以温习一下IOC
的知识。
1. set注入
set
注入是基于set
方法注入的,它的底层是通过反射机制调用属性对应的set
方法给属性赋值,这种方式必须要求属性对外提供set
方法,让两个对象之间产生关系。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.powernode</groupId>
<artifactId>spring6-002-dependency-injection</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<repositories>
<repository>
<id>repository.spring.milestone</id>
<name>Spring Milestone Repository</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.0-M2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
</project>
package com.powernode.spring6.dao;
/**
* @author 五度鱼
* @version 1.0
* @className UserDao
* @since 1.0
**/
public class UserDao {
public void insert(){
System.out.println("正在保存用户数据。");
}
}
package com.powernode.spring6.service;
import com.powernode.spring6.dao.UserDao;
/**
* @author 五度鱼
* @version 1.0
* @className UserService
* @since 1.0
**/
public class UserService {
private UserDao userDao;
// 使用set方式注入,必须提供set方法。
// 反射机制要调用这个方法给属性赋值的。
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void save(){
userDao.insert();
}
}
<?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 id="userDaoBean" class="com.powernode.spring6.dao.UserDao"/>
<bean id="userServiceBean" class="com.powernode.spring6.service.UserService">
<property name="userDao" ref="userDaoBean"/>
</bean>
</beans>
package com.powernode.spring6.test;
import com.powernode.spring6.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author 五度鱼
* @version 1.0
* @className DITest
* @since 1.0
**/
public class DITest {
@Test
public void testSetDI(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = applicationContext.getBean("userServiceBean", UserService.class);
userService.save();
}
}
运行结果:
实现原理:
-
<?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 id="userDaoBean" class="com.powernode.spring6.dao.UserDao"/> <bean id="userServiceBean" class="com.powernode.spring6.service.UserService"> <property name="userDao" ref="userDaoBean"/> </bean> </beans>
-
通过
property
标签获取到属性名:userDao
通过属性名推断出
set
方法名:setUserDao
通过反射机制调用
setUserDao()
方法给属性赋值property
标签的name
是属性名。property
标签的ref
是要注入的bean
对象的id
。(通过ref属性来完成bean的装配,这是bean最简单的一种装配方式。装配指的是:创建系统组件之间关联的动作)
(1)
setUsername()
演变为username
(2)
setPassword()
演变为password
(3)
setUserDao()
演变为userDao
(4)
setUserService()
演变为userService
2. 构造注入
核心原理:通过调用构造方法来给属性赋值。
package com.powernode.spring6.dao;
/**
* @author 五度鱼
* @version 1.0
* @className OrderDao
* @since 1.0
**/
public class OrderDao {
public void deleteById(){
System.out.println("正在删除订单。。。");
}
}
package com.powernode.spring6.service;
import com.powernode.spring6.dao.OrderDao;
/**
* @author 五度鱼
* @version 1.0
* @className OrderService
* @since 1.0
**/
public class OrderService {
private OrderDao orderDao;
// 通过反射机制调用构造方法给属性赋值
public OrderService(OrderDao orderDao) {
this.orderDao = orderDao;
}
public void delete(){
orderDao.deleteById();
}
}
<bean id="orderDaoBean" class="com.powernode.spring6.dao.OrderDao"/>
<bean id="orderServiceBean" class="com.powernode.spring6.service.OrderService">
<!--index="0"表示构造方法的第一个参数,将orderDaoBean对象传递给构造方法的第一个参数。-->
<constructor-arg index="0" ref="orderDaoBean"/>
</bean>
@Test
public void testConstructorDI(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
OrderService orderServiceBean = applicationContext.getBean("orderServiceBean", OrderService.class);
orderServiceBean.delete();
}
运行结果如下:
如果构造方法有两个参数:
package com.powernode.spring6.service;
import com.powernode.spring6.dao.OrderDao;
import com.powernode.spring6.dao.UserDao;
/**
* @author 五度鱼
* @version 1.0
* @className OrderService
* @since 1.0
**/
public class OrderService {
private OrderDao orderDao;
private UserDao userDao;
// 通过反射机制调用构造方法给属性赋值
public OrderService(OrderDao orderDao, UserDao userDao) {
this.orderDao = orderDao;
this.userDao = userDao;
}
public void delete(){
orderDao.deleteById();
userDao.insert();
}
}
Spring
配置文件:
<bean id="orderDaoBean" class="com.powernode.spring6.dao.OrderDao"/>
<bean id="orderServiceBean" class="com.powernode.spring6.service.OrderService">
<!--第一个参数下标是0-->
<constructor-arg index="0" ref="orderDaoBean"/>
<!--第二个参数下标是1-->
<constructor-arg index="1" ref="userDaoBean"/>
</bean>
<bean id="userDaoBean" class="com.powernode.spring6.dao.UserDao"/>
执行测试程序:
不使用参数下标,使用参数的名字可以吗?
<bean id="orderDaoBean" class="com.powernode.spring6.dao.OrderDao"/>
<bean id="orderServiceBean" class="com.powernode.spring6.service.OrderService">
<!--这里使用了构造方法上参数的名字-->
<constructor-arg name="orderDao" ref="orderDaoBean"/>
<constructor-arg name="userDao" ref="userDaoBean"/>
</bean>
<bean id="userDaoBean" class="com.powernode.spring6.dao.UserDao"/>
执行测试程序:
不指定参数下标,不指定参数名字,可以吗?
<bean id="orderDaoBean" class="com.powernode.spring6.dao.OrderDao"/>
<bean id="orderServiceBean" class="com.powernode.spring6.service.OrderService">
<!--没有指定下标,也没有指定参数名字-->
<constructor-arg ref="orderDaoBean"/>
<constructor-arg ref="userDaoBean"/>
</bean>
<bean id="userDaoBean" class="com.powernode.spring6.dao.UserDao"/>
执行测试程序:
配置文件中构造方法参数的类型顺序和构造方法参数的类型顺序不一致呢?
<bean id="orderDaoBean" class="com.powernode.spring6.dao.OrderDao"/>
<bean id="orderServiceBean" class="com.powernode.spring6.service.OrderService">
<!--顺序已经和构造方法的参数顺序不同了-->
<constructor-arg ref="userDaoBean"/>
<constructor-arg ref="orderDaoBean"/>
</bean>
<bean id="userDaoBean" class="com.powernode.spring6.dao.UserDao"/>
执行测试程序:
通过测试得知,通过构造方法注入的时候:
- 可以通过下标
- 可以通过参数名
- 也可以不指定下标和参数名,可以类型自动推断。
Spring
在装配方面做的比较健壮。
3. p命名空间注入
目的:简化配置。
使用p
命名空间注入的前提条件包括两个:
- 第一:在XML头部信息中添加p命名空间的配置信息:xmlns:p=”http://www.springframework.org/schema/p”
- 第二:p命名空间注入是基于
setter
方法的,所以需要对应的属性提供setter
方法。
package com.powernode.spring6.beans;
/**
* @author 五度鱼
* @version 1.0
* @className Customer
* @since 1.0
**/
public class Customer {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Customer{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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 id="customerBean" class="com.powernode.spring6.beans.Customer" p:name="zhangsan" p:age="20"/>
</beans>
@Test
public void testP(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-p.xml");
Customer customerBean = applicationContext.getBean("customerBean", Customer.class);
System.out.println(customerBean);
}
执行结果:
4. c命名空间注入
c
命名空间是简化构造方法注入的。
使用c
命名空间的两个前提条件:
第一:需要在xml
配置文件头部添加信息:xmlns:c=“http://www.springframework.org/schema/c”
第二:需要提供构造方法。
package com.powernode.spring6.beans;
/**
* @author 五度鱼
* @version 1.0
* @className MyTime
* @since 1.0
**/
public class MyTime {
private int year;
private int month;
private int day;
public MyTime(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
@Override
public String toString() {
return "MyTime{" +
"year=" + year +
", month=" + month +
", day=" + day +
'}';
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
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 id="myTimeBean" class="com.powernode.spring6.beans.MyTime" c:year="1970" c:month="1" c:day="1"/>-->
<bean id="myTimeBean" class="com.powernode.spring6.beans.MyTime" c:_0="2008" c:_1="8" c:_2="8"/>
</beans>
@Test
public void testC(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-c.xml");
MyTime myTimeBean = applicationContext.getBean("myTimeBean", MyTime.class);
System.out.println(myTimeBean);
}
执行结果:
最后求个关注,点赞,收藏,谢谢!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/87532.html