1.Set注入实现DI:
set注入:基于set方法实现的,
底层会通过反射机制调用属性对应的set方法然后给属性赋值
。这种方式要求属性必须对外提供set方法
1.1.编码实现:
a.新建模块:
b.pom.xml
引入依赖:
<?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>
c.引入实体类:
- 1.
UserDao.java
package com.jianqun.dao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserDao {
private static final Logger logger = LoggerFactory.getLogger(UserDao.class);
public void insert(){
logger.info("数据库正在保存用户信息");
}
}
- 2.
UserService.java
:
package com.jianqun.service;
import com.jianqun.dao.UserDao;
public class UserService {
private UserDao userDao;
//set注入的话,必须提供一个set方法
//Spring容器会使用这个set方法来给userDao属性赋值
//我自己写一个set方法,不使用IDEA工具自动生成的。就是不太符合javaBean规范
//我是为了测试某个属性要写什么值来方便说明才这么干的
public void setMySQLUserDao(UserDao xyz){
this.userDao = xyz;
}
// 这个是IDEA工具自动生成的set方法,符合javaBean规范
//public void setUserDao(UserDao userDao) {
// this.userDao = userDao;
//}
public void saveUser(){
//保存用户信息方法,
userDao.insert();
}
}
d.编写配置文件:
- 1.
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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDaoBean" class="com.jianqun.dao.UserDao"/>
<bean id="userServiceBean" class="com.jianqun.service.UserService">
<!--
想要Spring调用对应的set方法,需要配置property标签
name属性怎么写指定的值:set方法的方法名,去掉set,然后把剩下的单词首字母小写,写在这里就可以了
ref属性:翻译为引用,ref后面指定的是要注入bean的id
-->
<property name="mySQLUserDao" ref="userDaoBean"></property>
</bean>
</beans>
e.测试程序:
package com.jianqun.jianqun.bean;
import com.jianqun.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestUserService {
@Test
public void testSetDi(){
// 初始化Spring容器上下文(解析beans.xml文件,创建所有的bean对象)
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
// 根据id获取bean对象
UserService userServiceBean = applicationContext.getBean("userServiceBean", UserService.class);
userServiceBean.saveUser();
}
}
1.2.实现原理:
a.原理推断:
<?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.jianqun.dao.UserDao"/>
<bean id="userServiceBean" class="com.jianqun.service.UserService">
<!--
想要Spring调用对应的set方法,需要配置property标签
name属性怎么写指定的值:set方法的方法名,去掉set,然后把剩下的单词首字母小写,写在这里就可以了
ref属性:翻译为引用,ref后面指定的是要注入bean的id
-->
<property name="mySQLUserDao" ref="userDaoBean"></property>
</bean>
</beans>
- 1.获取property标签name属性的值:mySQLUserDao
- 2.通过这个值推断出set方法名:setMySQLUserDao
- 3.通过反射机制调用setMySQLUserDao()方法给属性赋值
- 5.property标签的ref是要注入的bean对象的id。(通过ref属性来完成bean的装配,这是bean最简单的一种装配方式。装配指的是:
创建系统组件之间关联的动作
)
b.可以把set方法注释掉,再测试一下:
- 1.通过测试得知,
底层实际上调用了setUserDao()方法
。所以需要确保这个方法的存在。现在我们把属性名修改一下,但方法名还是setUserDao(),我们来测试一下:
package com.powernode.spring6.service;
import com.powernode.spring6.dao.UserDao;
/**
**/
public class UserService {
private UserDao aaa;
// 使用set方式注入,必须提供set方法。
// 反射机制要调用这个方法给属性赋值的。
public void setUserDao(UserDao userDao) {
this.aaa = userDao;
}
public void save(){
aaa.insert();
}
}
- 2.通过测试看到程序仍然可以正常执行,
说明property标签的name是:setUserDao()方法名演变得到的。演变的规律是:
- setUsername() 演变为 username
- setPassword() 演变为 password
- setUserDao() 演变为 userDao
- setUserService() 演变为 userService
- 3.另外,对于property标签来说,
ref属性也可以采用标签的方式
,但使用ref属性是多数的:
<bean id="userServiceBean" class="com.powernode.spring6.service.UserService">
<property name="userDao">
<ref bean="userDaoBean"/>
</property>
</bean>
总结:set注入的核心实现原理:通过反射机制调用set方法来给属性赋值,让两个对象之间产生关系
1.3.set注入专题:
在日常开发中,使用
set注入的情况比较多
,所以我们就以set注入作为专题来记录了
a.注入外部bean:
a1.特点:
- 1.bean定义到外面,
在property标签中使用ref属性进行注入
。通常这种方式是常用
a2.案例1:
-
1.OrderDao.java
-
2.定义orderService.java:
-
3.配置文件:
-
4.测试用例:
a3.案例2:
1.有两个类 service 类和dao类,在
service 调用 dao 里面的方法
,在 spring 配置文件中进行配置
-
1.创建UserDao接口
-
2.创建Dao接口的实现类:
-
3.创建UserService类:
我们想实现的是在UserService中调用UserDao方法
—>传统方式:
在Spring中实现的方式:
- 1.现在我们使用了Spring,那么原始方式就就舍弃了,使用Spring来实现的话,就是通过在Spring的配置中来实现,
在UserService中把Dao注入进去
,在配置文件中,创建两个类的对象;<?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"> <!-- 创建service对象--> 、 <bean id="userService" class="com.jianqun.Spring5_4.service.UserService"> </bean> <!--创建dao对象--> <bean id="userDaoImpl" class="com.jianqun.Spring5_4.dao.UserDaoImpl"> </bean> </beans>
- 2.把userDao对象注入UsrService就可以了(在注入的时候,相当于注入一个对象)
<?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"> <!--创建dao对象--> <bean id="userDaoImpl" class="com.jianqun.Spring5_4.dao.UserDaoImpl"></bean> <!-- 创建service对象--> <bean id="userService" class="com.jianqun.Spring5_4.service.UserService"> <!--注入userDaodao对象 name:属性值:类里面属性名称 ref属性:创建的userDao对象bean标签的属性值,通过id值,把dao对象注入到userService对象中 --> <property name="userDao" ref="userDaoImpl"></property> </bean> </beans>
- 3.代码目录:
b.注入内部bean:
b1.特点:
在
property标签内部使用嵌套的bean标签,这就是内部bean
b2.案例1:
-
1.创建UserDao接口
-
2.创建Dao接口的实现类:
-
3.创建UserService类:
-
4.配置实现:
-
5.测试:
b2.案例2:
- 1.
一对多关系:
部门和员工;一个部门有多个员工,一个员工属于一个部门 ,部门是一,员工是多
- 2.在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示
定义实体类:
实现内部bean配置:
测试:
c.注入简单类型
c1.特点:
- 1.简单类型就是指的基本数据类型、包装类、String类型、枚举等
c2.注入简单类型举例1:
-
1.定义实体类:
-
2.在set-di.xml配置文件配置:
-
3.单元测试:
c3.在Spring中哪些属于是简单类型:
- 1.面试会考简单类型都有哪些,我们通过Spring的源码来分析BeanUtils类发现简单类型包括“
- 基本数据类型
- 基本数据类型对应的包装类
- String或其他的CharSequence子类
- Number子类
- Date子类
- Enum子类
- URI
- URL
- Temporal子类
- Locale
- Class
- 另外还包括以上简单值类型对应的数组类型
- 2.对于8种包装类: java中的数据类型int,double等不是对象,无法通过向上转型获取到Object提供的方法,而像String却可以,只因为String是一个对象而不是一个类型。基本数据类型由于这样的特性,导致无法参与转型,泛型,反射等过程。为了弥补这个缺陷,java提供了包装类。
c4.测试各个简单类型:
- 1.定义实体类:
- 2.配置文件配置:
- 3.测试:
- 4.日期类型说明:
c5.简单类型注入的经典应用:给数据源的属性注入值:
- 1.假设我们现在要自己手写一个数据源,我们都知道
所有的数据源都要实现javax.sql.DataSource接口
,并且数据源中应该有连接数据库的信息,例如:driver、url、username、password等。- 2.什么是数据源??数据源就是能够提供Connection对象的,都是数据源
- 1.编写类并实现DataSource接口 :
package com.powernode.spring6.beans;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
public class MyDataSource implements DataSource {
private String driver;
private String url;
private String username;
private String password;
public void setDriver(String driver) {
this.driver = driver;
}
public void setUrl(String url) {
this.url = url;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "MyDataSource{" +
"driver='" + driver + '\'' +
", url='" + url + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
@Override
public Connection getConnection() throws SQLException {
return null;
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
}
- 2.编写配置文件:我们给driver、url、username、password四个属性分别提供了setter方法,我们可以使用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">
<bean id="dataSource" class="com.powernode.spring6.beans.MyDataSource">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
</beans>
- 3.测试程序:
@Test
public void testDataSource(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-datasource.xml");
MyDataSource dataSource = applicationContext.getBean("dataSource", MyDataSource.class);
System.out.println(dataSource);
}
d.级联赋值
d1.案例1:
- 1.定义Clazz类:
package com.jianqun.beans;
public class Clazz {
private String name;
public Clazz() {
}
public Clazz(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Clazz{" +
"name='" + name + '\'' +
'}';
}
}
- 2.定义Student类:
package com.jianqun.beans;
public class Student {
private String name;
private Clazz clazz;
public Student() {
}
public Student(String name, Clazz clazz) {
this.name = name;
this.clazz = clazz;
}
public void setName(String name) {
this.name = name;
}
public void setClazz(Clazz clazz) {
this.clazz = clazz;
}
public Clazz getClazz() {
return clazz;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", clazz=" + clazz +
'}';
}
}
- 3.定义配置文件:spring-cascade.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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="clazzBean" class="com.jianqun.beans.Clazz"/> </bean>
<bean id="studentBean" class="com.jianqun.beans.Student">
<property name="name" value="张三"/>
<!--要点1:以下两行配置的顺序不能颠倒,先把班级对象注入过来,拿到班级对象后,再操作这个对象中的属性名-->
<property name="clazz" ref="clazzBean"/>
<!--要点2:clazz属性必须有getter方法-->
<property name="clazz.name" value="高三一班"/>
</bean>
</beans>
- 4.定义程序:
@Test
public void testCascade(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-cascade.xml");
Student student = applicationContext.getBean("studentBean", Student.class);
System.out.println(student);
}
要点:
在spring配置文件中,如上,注意顺序
在spring配置文件中,clazz属性必须提供getter方法
d2.案例2:
-
1.定义部门类:
-
2.定义员工类:
-
3.级联赋值:
外部bean赋值:
级联赋值:
- 4.测试:
e.注入数组
e1.当数组中的元素是简单类型:
- 1.定义Person类:
package com.jianqun.beans;
import java.util.Arrays;
public class Person {
private String[] favariteFoods;
public void setFavariteFoods(String[] favariteFoods) {
this.favariteFoods = favariteFoods;
}
@Override
public String toString() {
return "Person{" +
"favariteFoods=" + Arrays.toString(favariteFoods) +
'}';
}
}
- 2.编写配置文件:spring-array-simple.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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="person" class="com.jianqun.beans.Person">
<property name="favariteFoods">
<array>
<value>鸡排</value>
<value>汉堡</value>
<value>鹅肝</value>
</array>
</property>
</bean>
</beans>
- 3.测试代码:
@Test
public void testArraySimple(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-array-simple.xml");
Person person = applicationContext.getBean("person", Person.class);
System.out.println(person);
}
e2.当数组中的元素是非简单类型:一个订单中包含多个商品。
- 1.定义实体类:
package com.jianqun.beans;
public class Goods {
private String name;
public Goods() {
}
public Goods(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
'}';
}
}
- 2.订单类:
package com.jianqun.beans;
import java.util.Arrays;
public class Order {
// 一个订单中有多个商品
private Goods[] goods;
public Order() {
}
public Order(Goods[] goods) {
this.goods = goods;
}
public void setGoods(Goods[] goods) {
this.goods = goods;
}
@Override
public String toString() {
return "Order{" +
"goods=" + Arrays.toString(goods) +
'}';
}
}
- 3.配置文件:spring-array.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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="goods1" class="com.jianqun.beans.Goods">
<property name="name" value="西瓜"/>
</bean>
<bean id="goods2" class="com.jianqun.beans.Goods">
<property name="name" value="苹果"/>
</bean>
<bean id="order" class="com.jianqun.beans.Order">
<property name="goods">
<array>
<!--这里使用ref标签即可-->
<ref bean="goods1"/>
<ref bean="goods2"/>
</array>
</property>
</bean>
</beans>
- 4.测试代码:
@Test
public void testArray(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-array.xml");
Order order = applicationContext.getBean("order", Order.class);
System.out.println(order);
}
总结:要点:
如果数组中是简单类型
,使用value标签
如果数组中是非简单类型
,使用ref标签
f.注入List集合
f1.编码实现:List集合是有序可重复的:
package com.jiaqun.beans;
import java.util.List;
public class People {
// 一个人有多个名字
private List<String> names;
public void setNames(List<String> names) {
this.names = names;
}
@Override
public String toString() {
return "People{" +
"names=" + names +
'}';
}
}
- 2.配置文件:spring-collection.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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="peopleBean" class="com.jianqun.beans.People">
<property name="names">
<list>
<value>铁锤</value>
<value>张三</value>
<value>张三</value>
<value>张三</value>
<value>狼</value>
</list>
</property>
</bean>
</beans>
- 3.测试程序:
@Test
public void testCollection(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-collection.xml");
People peopleBean = applicationContext.getBean("peopleBean", People.class);
System.out.println(peopleBean);
}
注意:注入List集合的时候使用list标签,如果List集合中是简单类型使用value标签,反之使用ref标签。
g.注入Set集合:
g1.Set集合:
Set集合是无序不可重复的
- 1.定义实体类:
package com.jiaqun.beans;
import java.util.List;
import java.util.Set;
public class People {
// 一个人有多个电话
private Set<String> phones;
public void setPhones(Set<String> phones) {
this.phones = phones;
}
//......
@Override
public String toString() {
return "People{" +
"phones=" + phones +
", names=" + names +
'}';
}
}
- 2.定义配置类:
<?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="peopleBean" class="com.jianqun.beans.People">
<property name="phones">
<set>
<!--非简单类型可以使用ref,简单类型使用value-->
<value>110</value>
<value>110</value>
<value>120</value>
<value>120</value>
<value>119</value>
<value>119</value>
</set>
</property>
</bean>
</beans>
要点:
使用<set>标签
set集合中元素是简单类型的使用value标签,反之使用ref标签
- 3.测试:
h.注入Map集合
h1.定义实体类:
package com.powernode.spring6.beans;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class People {
// 一个人有多个住址
private Map<Integer, String> addrs;
public void setAddrs(Map<Integer, String> addrs) {
this.addrs = addrs;
}
//......
@Override
public String toString() {
return "People{" +
"addrs=" + addrs +
", phones=" + phones +
", names=" + names +
'}';
}
}
- 2.编写配置文件:spring-collection.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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="peopleBean" class="com.jianqun.beans.People">
<property name="addrs">
<map>
<!--如果key不是简单类型,使用 key-ref 属性-->
<!--如果value不是简单类型,使用 value-ref 属性-->
<entry key="1" value="北京大兴区"/>
<entry key="2" value="上海浦东区"/>
<entry key="3" value="深圳宝安区"/>
</map>
</property>
</bean>
</beans>
要点:使用
h2.注入数组 + 注入List集合 + 注入Set集合 + 注入Map集合(基本数据类型)
- 1.创建类,在类中定义数组,集合类型的属性
package com.jianqun.spring5.collectiontype;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author jianqun
* @email:1033586391@qq.com
* @creat 2022-02-06-14:07
*/
public class Stu {
//数组类型属性
private String[] courses;
public void setCourses(String[] courses) {
this.courses = courses;
}
//list集合类型
private List<String> list;
public void setList(List<String> list) {
this.list = list;
}
//set集合类型
private Set<String> sets;
public void setSets(Set<String> sets) {
this.sets = sets;
}
//Map集合类型
private Map<String,String> maps;
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
}
- 2.在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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--集合类型的属性注入-->
<bean id="stu" class="com.jianqun.spring5.collectiontype.Stu">
<!-- 数组类型的属性注入-->
<property name="courses">
<array>
<value>PHP</value>
<value>Database</value>
</array>
</property>
<!-- list集合类型的属性注入-->
<property name="list">
<list>
<value>PHP</value>
<value>Database</value>
</list>
</property>
<!-- set类型的属性注入-->
<property name="sets">
<set>
<value>Mysql</value>
<value>Redis</value>
</set>
</property>
<!-- map类型的属性注入-->
<property name="maps">
<map>
<entry key="JAVA" value="java"></entry>
<entry key="PHP" value="php"></entry>
</map>
</property>
</bean>
</beans>
- 3.测试输出结果
package com.jianqun.spring5.test;
import com.jianqun.spring5.collectiontype.Stu;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author jianqun
* @email:1033586391@qq.com
* @creat 2022-02-06-14:28
*/
public class TestSpring {
@Test
public void test1(){
//解析xml文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
//反射得到类对象
Stu stu = context.getBean("stu", Stu.class);
//对象调方法
stu.test();
}
}
- 4.输出结果
h3.注入数组 + 注入List集合 + 注入Set集合 + 注入Map集合(对象类型值)
- 1.定义类:
// 课程类
package com.jianqun.spring5.collectiontype;
/**
* @author jianqun
* @email:1033586391@qq.com
* @creat 2022-02-06-15:16
*/
//课程类
public class Course {
private String cname;
public void setCname(String cname) {
this.cname = cname;
}
}
//学生类
package com.jianqun.spring5.collectiontype;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author jianqun
* @email:1033586391@qq.com
* @creat 2022-02-06-14:07
*/
public class Stu {
//学生所学的多门课程,存放的不再是字符串类型,而是课程类型
private List<Course> courseslists;
public void setCourseslists(List<Course> courseslists) {
this.courseslists = courseslists;
}
public void test(){
}
}
//配置文件
<?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="stu" class="com.jianqun.spring5.collectiontype.Stu">
<!-- 注入list集合类型的 值是个对象 -->
<property name="courseslists">
<list>
<ref bean="courses1"></ref>
<ref bean="courses2"></ref>
</list>
</property>
</bean>
<!-- 定义多个course对象-->
<bean id="courses1" class="com.jianqun.spring5.collectiontype.Course">
<property name="cname" value="JAVA1111"></property>
</bean>
<bean id="courses2" class="com.jianqun.spring5.collectiontype.Course">
<property name="cname" value="JAVA222"></property>
</bean>
</beans>
package com.jianqun.spring5.test;
import com.jianqun.spring5.collectiontype.Course;
import com.jianqun.spring5.collectiontype.Stu;
import com.jianqun.spring5.factorybean.MyBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author jianqun
* @email:1033586391@qq.com
* @creat 2022-02-06-14:28
*/
// 编码测试
public class TestSpring {
@Test
public void test2(){
//解析xml文件
ClassPathXmlApplicationContext context2 = new ClassPathXmlApplicationContext("bean1.xml");
//反射得到类对象
Stu stu = context2.getBean("stu", Stu.class);
//对象调方法
System.out.println(stu);
}
}
把集合注入部分提取出来,作为公共部分,避免仅仅在一个类中可用
- 1.定义Book类
package com.jianqun.spring5.collectiontype;
import java.util.List;
/**
* @author jianqun
* @email:1033586391@qq.com
* @creat 2022-02-06-15:36
*/
public class Book {
private List<String> list;
public void setList(List<String> list) {
this.list = list;
}
public void test(){
System.out.println("list:" + list);
}
}
- 2.引入util名称空间
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
</beans>
- 3.使用util标签完成list集合 的注入提取
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 属性值 -->
<util:list id="booklist">
<value>java</value>
<value>php</value>
<value>sql</value>
</util:list>
<!-- 提取list集合的类型 -->
<bean id="book" class="com.jianqun.spring5.collectiontype.Book">
<property name="list" ref="booklist"></property>
</bean>
</beans>
- 4.测试
package com.jianqun.spring5.test;
import com.jianqun.spring5.collectiontype.Book;
import com.jianqun.spring5.collectiontype.Course;
import com.jianqun.spring5.collectiontype.Stu;
import com.jianqun.spring5.factorybean.MyBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author jianqun
* @email:1033586391@qq.com
* @creat 2022-02-06-14:28
*/
public class TestSpring {
@Test
public void test3(){
//解析xml文件
ClassPathXmlApplicationContext context2 = new ClassPathXmlApplicationContext("bean2.xml");
//反射得到类对象
Book book = context2.getBean("book", Book.class);
//对象调方法
book.test();
}
- 输出结果
J.注入Properties
J1.特点:
- 1.
java.util.Properties继承java.util.Hashtable
,所以Properties也是一个Map集合
。
J2.编码实现:
- 1.定义类:
package com.jianqun.beans;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class People {
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
//......
@Override
public String toString() {
return "People{" +
"properties=" + properties +
", addrs=" + addrs +
", phones=" + phones +
", names=" + names +
'}';
}
}
- 2.配置文件编写:
<?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="peopleBean" class="com.powernode.spring6.beans.People">
<property name="properties">
<props>
<prop key="driver">com.mysql.cj.jdbc.Driver</prop>
<prop key="url">jdbc:mysql://localhost:3306/spring</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
</beans>
要点:
使用<props>标签嵌套<prop>标签完成
- 3.测试:
K.注入null和空字符串
K1.特点:
- 1.注入空字符串使用:
<value/>
或者value=""
- 2.注入null使用:
<null/>
或者不为该属性赋值
K2.注入空字符串:
- 1.定义实体类:vip
package com.jianqun.beans;
public class Vip {
private String email;
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "Vip{" +
"email='" + email + '\'' +
'}';
}
}
- 2.配置文件编写:
spring-null.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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="vipBean" class="com.jianqun.beans.Vip">
<!--空串的第一种方式-->
<!--<property name="email" value=""/>-->
<!--空串的第二种方式-->
<property name="email">
<value/>
</property>
</bean>
</beans>
- 3.测试:
@Test
public void testNull(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-null.xml");
Vip vipBean = applicationContext.getBean("vipBean", Vip.class);
System.out.println(vipBean);
}
K3.怎么注入null:
- 1.配置文件spring-null.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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="vipBean" class="com.jianqun.beans.Vip" />
</beans>
- 2.第二种方式:使用
<null/>
<?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="vipBean" class="com.powernode.spring6.beans.Vip">
<property name="email">
<null/>
</property>
</bean>
</beans>
L.注入的值中含有特殊符号:
L1.特殊符号问题:
- 1.XML中有5个特殊字符,分别是
:<、>、'、"、&
,以上5个特殊符号在XML中会被特殊对待,会被当做XML语法的一部分进行解析,如果这些特殊符号直接出现在注入的字符串当中,会报错
L2.解决方案包括两种:
- 1.第一种:特殊符号使用转义字符代替。
- 2.第二种:将含有特殊符号的字符串放到:
<![CDATA[]]>
当中。因为放在CDATA区中的数据不会被XML文件解析器解析。 - 3.
5个特殊字符对应的转义字符分别是
:- 特殊字符:> | 转义字符:>
- 特殊字符:< | 转义字符:<
- 特殊字符:’ | 转义字符:&apos
- 特殊字符:" | 转义字符:"
- 特殊字符:& | 转义字符:&
L3.编码实现:先使用转义字符来代替:
package com.jianqun.beans;
public class Math {
private String result;
public void setResult(String result) {
this.result = result;
}
@Override
public String toString() {
return "Math{" +
"result='" + result + '\'' +
'}';
}
}
- 2.配置文件:spring-special.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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="mathBean" class="com.powernode.spring6.beans.Math">
<property name="result" value="2 < 3"/>
</bean>
</beans>
- 3.测试程序:
@Test
public void testSpecial(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-special.xml");
Math mathBean = applicationContext.getBean("mathBean", Math.class);
System.out.println(mathBean);
}
L4.CDATA方式实现特殊符号赋值:
- 1.配置文件:spring-special.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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="mathBean" class="com.powernode.spring6.beans.Math">
<property name="result">
<!--只能使用value标签-->
<value><![CDATA[2 < 3]]></value>
</property>
</bean>
</beans>
注意:使用CDATA时,不能使用value属性,只能使用value标签。
1.4.P命名空间注入
a.p命名空间注入的目的:
- 1.是为了简化配置
- 2.使用p命名空间注入的前提条件包括两个:
- 第一:在XML头部信息中添加p命名空间的配置信息:
xmlns:p="http://www.springframework.org/schema/p"
- 第二:p命名空间注入是基于setter方法的,所以
需要对应的属性提供setter方法
- 第一:在XML头部信息中添加p命名空间的配置信息:
b.编码实现:
- 1.定义类:
package com.jianqun.beans;
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 +
'}';
}
}
- 3.配置文件:spring-p.xml
<?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>
- 4.测试程序:
- 5.把实体类中的set方法去掉来验证P命名空间方式是否依赖Set方法:
p命名空间实际上是对set注入的简化
1.5.util命名空间
a.util命名空间作用:
- 1.使用util命名空间可以
让配置复用
- 2.使用util命名空间的前提是:在spring配置文件头部添加配置信息。如下:
b.编码实现:
package com.powernode.spring6.beans;
import java.util.Properties;
public class MyDataSource1 {
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "MyDataSource1{" +
"properties=" + properties +
'}';
}
}
package com.powernode.spring6.beans;
import java.util.Properties;
public class MyDataSource2 {
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "MyDataSource2{" +
"properties=" + properties +
'}';
}
}
- 3.配置文件:spring-util.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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<util:properties id="prop">
<prop key="driver">com.mysql.cj.jdbc.Driver</prop>
<prop key="url">jdbc:mysql://localhost:3306/spring</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</util:properties>
<bean id="dataSource1" class="com.powernode.spring6.beans.MyDataSource1">
<property name="properties" ref="prop"/>
</bean>
<bean id="dataSource2" class="com.powernode.spring6.beans.MyDataSource2">
<property name="properties" ref="prop"/>
</bean>
</beans>
1.6.基于XML的自动装配:
- 1.Spring还可以完成自动化的注入,
自动化注入又被称为自动装配
。它可以根据名字进行自动装配
,也可以根据类型进行自动装配
a.根据名称自动装配:
a1.编码实现:
- 1.UserDao
package com.jianqun.dao;
public class UserDao {
public void insert(){
System.out.println("正在保存用户数据。");
}
}
- 2.UserService
package com.powernode.spring6.service;
import com.powernode.spring6.dao.UserDao;
public class UserService {
private UserDao aaa;
// 这个set方法非常关键
public void setAaa(UserDao aaa) {
this.aaa = aaa;
}
public void save(){
aaa.insert();
}
}
- 3.Spring的配置文件这样配置:spring-autowire.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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="com.powernode.spring6.service.UserService" autowire="byName"/>
<!-- id一般也叫做是bean的名称,根据名称匹配的话,就和实体类中的set方法一样,把set去掉,然后第一个字母变小写-->
<bean id="aaa" class="com.powernode.spring6.dao.UserDao"/>
</beans>
这个配置起到关键作用:
- UserService Bean中需要添加
autowire="byName"
,表示通过名称进行装配
- UserService类中有一个UserDao属性,
而UserDao属性的名字是aaa,对应的set方法是setAaa(),正好和UserDao Bean的id是一样的
。这就是根据名称自动装配
- 4.测试:
@Test
public void testAutowireByName(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-autowire.xml");
UserService userService = applicationContext.getBean("userService", UserService.class);
userService.save();
}
a2.测试一下byName装配是和属性名有关还是和set方法名有关系:
package com.powernode.spring6.service;
import com.powernode.spring6.dao.UserDao;
public class UserService {
// 这里没修改
private UserDao aaa;
/*public void setAaa(UserDao aaa) {
this.aaa = aaa;
}*/
// set方法名变化了
public void setDao(UserDao aaa){
this.aaa = aaa;
}
public void save(){
aaa.insert();
}
}
- 2.在执行测试程序:
- 3.通过测试得知,aaa属性并没有赋值成功。也就是并没有装配成功。我们将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">
<bean id="userService" class="com.powernode.spring6.service.UserService" autowire="byName"/>
<!--这个id修改了-->
<bean id="dao" class="com.powernode.spring6.dao.UserDao"/>
</beans>
- 4.执行测试程序:
这说明,
如果根据名称装配(byName),底层会调用set方法进行注入
。例如:setAge() 对应的名字是age,setPassword()对应的名字是password,setEmail()对应的名字是email。
b.根据类型自动装配:
b1.编码实现:
- 1.定义AccountDao:
package com.powernode.spring6.dao;
public class AccountDao {
public void insert(){
System.out.println("正在保存账户信息");
}
}
- 1.定义service:
package com.powernode.spring6.service;
import com.powernode.spring6.dao.AccountDao;
public class AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void save(){
accountDao.insert();
}
}
- 3.配置文件:
<?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">
<!--byType表示根据类型自动装配-->
<bean id="accountService" class="com.powernode.spring6.service.AccountService" autowire="byType"/>
<bean class="com.powernode.spring6.dao.AccountDao"/>
</beans>
- 4.测试程序:
@Test
public void testAutowireByType(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-autowire.xml");
AccountService accountService = applicationContext.getBean("accountService", AccountService.class);
accountService.save();
}
b2.我们把UserService中的set方法注释掉,再执行:
- 1.可以看到无论是byName还是byType,在装配的时候都是基于set方法的。所以set方法是必须要提供的。提供构造方法是不行的,
- 2.如果byType,根据类型装配时,如果配置文件中有两个类型一样的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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="accountService" class="com.powernode.spring6.service.AccountService" autowire="byType"/>
<bean id="x" class="com.powernode.spring6.dao.AccountDao"/>
<bean id="y" class="com.powernode.spring6.dao.AccountDao"/>
</beans>
当byType进行自动装配的时候,配置文件中某种类型的Bean必须是唯一的,不能出现多个
2.构造注入方式实心依赖注入:
- 1.set注入是
对象产生之后
,再去给属性赋值 的时候注入的- 2.
构造注入
就是通过构造方法给属性赋值,它是在对象实例化
的时候进行注入的
2.1.编码实现:
- 1.
OrderDao.java
package com.jianqun.spring6.dao;
public class OrderDao {
public void deleteById(){
System.out.println("正在删除订单。。。");
}
}
- 2.
OrderService.java
package com.jianqun.service;
import com.jianqun.dao.OrderDao;
public class OrderService {
private OrderDao orderDao;
// 通过反射机制调用构造方法给属性赋值
public OrderService(OrderDao orderDao) {
this.orderDao = orderDao;
}
public void delete(){
orderDao.deleteById();
}
}
- 3.
Spring.xml
<bean id="orderDaoBean" class="com.jianqun.dao.OrderDao"/>
<bean id="orderServiceBean" class="com.jianqun.service.OrderService">
<!--index="0"表示构造方法的第一个参数,将orderDaoBean对象传递给构造方法的第一个参数。-->
<constructor-arg index="0" ref="orderDaoBean"/>
</bean>
- 4.测试程序:
@Test
public void testConstructorDI(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
OrderService orderServiceBean = applicationContext.getBean("orderServiceBean", OrderService.class);
orderServiceBean.delete();
}
- 5.运行结果:
2.2.如果构造方法有两个参数:
- 1.
OrderService.java
package com.jianqun.service;
import com.jianqun.dao.OrderDao;
import com.jianqun.dao.UserDao;
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();
}
}
- 2.spring配置文件:
<bean id="orderDaoBean" class="com.powernode.dao.OrderDao"/>
<bean id="orderServiceBean" class="com.powernode.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"/>
- 3.执行测试程序:
2.3.c命名空间注入
a.概述:
- 1.对于c命名空间是简化构造方法注入的。使用c命名空间的两个前提条件:
- 第一:需要在xml配置文件头部添加信息:
xmlns:c="http://www.springframework.org/schema/c
- 第二:需要提供构造方法
- 第一:需要在xml配置文件头部添加信息:
b.代码测试:
- 1.定义实体类:
package com.powernode.spring6.beans;
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 +
'}';
}
}
- 2.配置文件:spring-c.xml
<?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>
- 3.测试程序:测试程序
- 4.把实体类中的构造方法注释掉来验证是否依赖构造方法实现的:
c命名空间是依靠构造方法的
。- 注意:
不管是p命名空间还是c命名空间,注入的时候都可以注入简单类型以及非简单类型
2.4.其他注意事项:
a.不使用参数下标,使用参数的名字也可以
<bean id="orderDaoBean" class="com.jianqun.dao.OrderDao"/>
<bean id="orderServiceBean" class="com.jianqun.service.OrderService">
<!--这里使用了构造方法上参数的名字-->
<constructor-arg name="orderDao" ref="orderDaoBean"/>
<constructor-arg name="userDao" ref="userDaoBean"/>
</bean>
<bean id="userDaoBean" class="com.jianqun.spring6.dao.UserDao"/>
b.不指定参数下标,不指定参数名字,也可以
<bean id="orderDaoBean" class="com.jianqun.dao.OrderDao"/>
<bean id="orderServiceBean" class="com.jianqun.service.OrderService">
<!--没有指定下标,也没有指定参数名字-->
<constructor-arg ref="orderDaoBean"/>
<constructor-arg ref="userDaoBean"/>
</bean>
<bean id="userDaoBean" class="com.jianqun.dao.UserDao"/>
c.配置文件中构造方法参数的类型顺序和构造方法参数的类型顺序不一致无影响
<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"/>
2.5.总结:
- 通过测试得知,通过构造方法注入的时候:
- 可以通过下标
- 可以通过参数名
- 也可以不指定下标和参数名,可以类型自动推断
- Spring在装配方面做的还是比较健壮的
3.Spring引入外部属性配置文件
3.1.概述:
- 1.我们都知道编写数据源的时候是需要连接数据库的信息的,例如:driver url username password等信息。这些信息可以单独写到一个属性配置文件中吗,这样用户修改起来会更加的方便。当然可以
3.2.编码实现:
- 1.第一步:写一个数据源类,提供相关属性。
package com.powernode.spring6.beans;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
public class MyDataSource implements DataSource {
@Override
public String toString() {
return "MyDataSource{" +
"driver='" + driver + '\'' +
", url='" + url + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
private String driver;
private String url;
private String username;
private String password;
public void setDriver(String driver) {
this.driver = driver;
}
public void setUrl(String url) {
this.url = url;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
//......
}
- 2.第二步:在类路径下新建
jdbc.properties
文件,并配置信息
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root123
- 3.第三步:在spring配置文件中引入context命名空间。
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
- 4.第四步:在spring中配置使用jdbc.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"
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">
<context:property-placeholder location="jdbc.properties"/>
<bean id="dataSource" class="com.powernode.spring6.beans.MyDataSource">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
</beans>
- 5.测试程序:
@Test
public void testProperties(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-properties.xml");
MyDataSource dataSource = applicationContext.getBean("dataSource", MyDataSource.class);
System.out.println(dataSource);
}
- 6.执行结果: