根据 【动力节点】最新Spring框架教程,全网首套Spring6教程,跟老杜从零学spring入门到高级 以及老杜的原版笔记 https://www.yuque.com/docs/share/866abad4-7106-45e7-afcd-245a733b073f?# 《Spring6》 进行整理, 文档密码:mg9b
Spring 相关文章整理汇总归纳于:https://www.yuque.com/u27599042/zuisie
set注入专题
注入外部Bean
- 外部Bean:要进行注入的bean定义到需要被注入的Bean的外面
- 对于外部Bean,在property标签中使用ref属性进行注入,或者使用ref标签进行注入,其中通过ref属性进行注入是常用。
<!--声明/定义Bean--> <bean id="orderDaoBean" class="com.powernode.spring6.dao.OrderDao"></bean> <bean id="orderServiceBean" class="com.powernode.spring6.service.OrderService"> <!--使用ref属性来引入外部Bean,这就是注入外部Bean--> <property name="orderDao" ref="orderDaoBean"/> </bean>
注入内部Bean
- 内部Bean:在bean标签中嵌套bean标签,即需要进行注入的Bean通过Bean标签声明在需要被注入的Bean中,然后直接注入到需要被注入的Bean中。
<bean id="orderServiceBean2" class="com.powernode.spring6.service.OrderService"> <property name="orderDao"> <!--在property标签中使用嵌套的bean标签,这就是内部Bean--> <bean class="com.powernode.spring6.dao.OrderDao"></bean> </property> </bean>
注入简单类型
- 如果给简单类型赋值,即给属性注入简单类型,使用value属性或value标签,而不是ref。
public class User { private String username; // String是简单类型 private String password; private int age; // int是简单类型 public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + ", age=" + age + '}'; } }
<!--注入简单类型--> <bean id="userBean" class="com.powernode.spring6.bean.User"> <!--重点:如果是给简单类型赋值,就不能使用ref了。就需要使用value了。--> <property name="username" value="张三"/> <property name="password" value="123"/> <property name="age" value="20"/> </bean>
Spring 中的简单类型
- 通过BeanUtils类的源码分析得知,简单类型包括:
- 基本数据类型
- 基本数据类型对应的包装类
- String或其他的CharSequence子类
- Number子类
- Date子类,java.util.Date是简单类型
- Enum子类
- URI
- URL
- Temporal子类,Temporal是Java8提供的时间和时区类型
- Locale,Locale是语言类,也是简单类型。
- Class
- 另外还包括以上简单值类型对应的数组类型。
public class BeanUtils{ //....... /** * Check if the given type represents a "simple" property: a simple value * type or an array of simple value types. * <p>See {@link #isSimpleValueType(Class)} for the definition of <em>simple * value type</em>. * <p>Used to determine properties to check for a "simple" dependency-check. * @param type the type to check * @return whether the given type represents a "simple" property * @see org.springframework.beans.factory.support.RootBeanDefinition#DEPENDENCY_CHECK_SIMPLE * @see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#checkDependencies * @see #isSimpleValueType(Class) */ public static boolean isSimpleProperty(Class<?> type) { Assert.notNull(type, "'type' must not be null"); return isSimpleValueType(type) || (type.isArray() && isSimpleValueType(type.getComponentType())); } /** * Check if the given type represents a "simple" value type: a primitive or * primitive wrapper, an enum, a String or other CharSequence, a Number, a * Date, a Temporal, a URI, a URL, a Locale, or a Class. * <p>{@code Void} and {@code void} are not considered simple value types. * @param type the type to check * @return whether the given type represents a "simple" value type * @see #isSimpleProperty(Class) */ public static boolean isSimpleValueType(Class<?> type) { return (Void.class != type && void.class != type && (ClassUtils.isPrimitiveOrWrapper(type) || Enum.class.isAssignableFrom(type) || CharSequence.class.isAssignableFrom(type) || Number.class.isAssignableFrom(type) || Date.class.isAssignableFrom(type) || Temporal.class.isAssignableFrom(type) || URI.class == type || URL.class == type || Locale.class == type || Class.class == type)); } //........ }
测试所有的简单类型
- 编写一个程序,把所有的简单类型全部测试一遍:
package com.powernode.spring6.beans; import java.net.URI; import java.net.URL; import java.time.LocalDate; import java.util.Date; import java.util.Locale; public class A { private byte b; private short s; private int i; private long l; private float f; private double d; private boolean flag; private char c; private Byte b1; private Short s1; private Integer i1; private Long l1; private Float f1; private Double d1; private Boolean flag1; private Character c1; private String str; private Date date; private Season season; private URI uri; private URL url; private LocalDate localDate; private Locale locale; private Class clazz; // 生成setter方法 // 生成toString方法 } enum Season { SPRING, SUMMER, AUTUMN, WINTER }
- 需要注意的是:
- 如果把Date当做简单类型的话,日期字符串格式不能随便写,格式必须符合Date的toString()方法格式。显然这就比较鸡肋了。如果我们提供一个这样的日期字符串:2010-10-11,在这里是无法赋值给Date类型的属性的。
- spring6之后,当注入的是URL,那么这个url字符串是会进行有效性检测的。如果是一个存在的url,那就没问题。如果不存在则报错。
注入简单类型经典案例
- 经典案例:给数据源的属性注入值:
- 假设我们现在要自己手写一个数据源,我们都知道所有的数据源都要实现javax.sql.DataSource接口,并且数据源中应该有连接数据库的信息,例如:driver、url、username、password 等。
- 数据源:能够给你提供Connection对象的,都是数据源
/** * 所有的数据源都要实现java规范:javax.sql.DataSource **/ public class MyDataSource implements DataSource { // 可以把数据源交给Spring容器来管理。 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 { // 获取数据库连接对象的时候需要4个信息:driver url username password 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; } }
<!--让spring来管理我们的数据源--> <bean id="myDataSource" class="com.powernode.spring6.jdbc.MyDataSource"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/spring6"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean>
@Test public void testDataSource(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-datasource.xml"); MyDataSource dataSource = applicationContext.getBean("dataSource", MyDataSource.class); System.out.println(dataSource); }
级联属性赋值
// 班级类 public class Clazz { // 班级名称 private String name; public void setName(String name) { this.name = name; } @Override public String toString() { return "Clazz{" + "name='" + name + '\'' + '}'; } }
public class Student { private String name; // 学生属于哪个班级 private Clazz clazz; public void setClazz(Clazz clazz) { this.clazz = clazz; } // 使用级联属性赋值,这个需要这个get方法。 // 因为级联给学生所在的班级属性赋值会调用学生的getClazz()方法 public Clazz getClazz() { return clazz; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", clazz=" + clazz + '}'; } }
- 原先的注入方法
<bean id="studentBean" class="com.powernode.spring6.bean.Student"> <!--简单类型,使用value--> <property name="name" value="张三"/> <!--这不是简单类型,使用ref--> <property name="clazz" ref="clazzBean"/> </bean> <bean id="clazzBean" class="com.powernode.spring6.bean.Clazz"> <property name="name" value="高三一班"/> </bean>
- 级联注入:
- 注意:级联属性赋值,对于对其他对象引用的成员变量,一定要提供get方法,因为进行级联属性赋值时,需要先调用get方法获取对其他对象引用的成员变量,然后再调用该成员变量属性的set方法进行属性赋值
<!--使用级联属性赋值需要注意两点: 1. 配置的顺序不能颠倒,必须如下顺序。 2. clazz属性必须提供getter方法。 --> <bean id="studentBean" class="com.powernode.spring6.bean.Student"> <!--简单类型,使用value--> <property name="name" value="张三"/> <!--这不是简单类型,使用ref--> <!-- 因为后面要对该对象的属性赋值,所以必须先有该对象 --> <property name="clazz" ref="clazzBean"/> <!--级联属性赋值--> <!-- name="clazz.name" 会调用学生的getClazz()方法, 所以学生类必须提供getClazz()方法,然后调用set方法给班级的name赋值 --> <property name="clazz.name" value="高三二班"/> </bean> <!-- 这里不进行注入 --> <bean id="clazzBean" class="com.powernode.spring6.bean.Clazz"></bean>
注入数组
数组中的元素是简单类型
public class QianDaYe { private String[] aiHaos; public void setAiHaos(String[] aiHaos) { this.aiHaos = aiHaos; } @Override public String toString() { return "QianDaYe{" + "aiHaos=" + Arrays.toString(aiHaos) + '}'; } }
<bean id="yuQian" class="com.powernode.spring6.bean.QianDaYe"> <!-- 这个数组属性当中的元素类型是String,是简单类型 --> <property name="aiHaos"> <array> <value>抽烟</value> <value>喝酒</value> <value>烫头</value> </array> </property> </bean>
数组中的元素是非简单类型
public class Woman { private String name; public void setName(String name) { this.name = name; } @Override public String toString() { return "Woman{" + "name='" + name + '\'' + '}'; } }
public class QianDaYe { private String[] aiHaos; // 多个女性朋友 private Woman[] womens; public void setWomens(Woman[] womens) { this.womens = womens; } public void setAiHaos(String[] aiHaos) { this.aiHaos = aiHaos; } @Override public String toString() { return "QianDaYe{" + "aiHaos=" + Arrays.toString(aiHaos) + ", womens=" + Arrays.toString(womens) + '}'; } }
<bean id="w1" class="com.powernode.spring6.bean.Woman"> <property name="name" value="小花"/> </bean> <bean id="w2" class="com.powernode.spring6.bean.Woman"> <property name="name" value="小亮"/> </bean> <bean id="w3" class="com.powernode.spring6.bean.Woman"> <property name="name" value="小明"/> </bean> <bean id="yuQian" class="com.powernode.spring6.bean.QianDaYe"> <!-- 这个数组属性当中的元素类型是String简单类型 --> <property name="aiHaos"> <array> <value>抽烟</value> <value>喝酒</value> <value>烫头</value> </array> </property> <!-- 这个数组当中的类型就不是简单类型了--> <property name="womens"> <array> <ref bean="w1"/> <ref bean="w2"/> <ref bean="w3"/> </array> </property> </bean>
注入数组小结
- 如果数组中是简单类型,使用value标签。
- 如果数组中是非简单类型,使用ref标签。
注入List集合与Set集合
- List集合:有序可重复
- 注意:注入List集合的时候使用list标签,如果List集合中是简单类型使用value标签,反之使用ref标签。
- Set集合:无序不可重复
- 要点: 注入set集合的时候使用
<set>
标签,如果set集合中元素是简单类型的使用value标签,反之使用ref标签。
public class Person { // 注入List集合 private List<String> names; // 注入Set集合 private Set<String> addrs; public void setNames(List<String> names) { this.names = names; } public void setAddrs(Set<String> addrs) { this.addrs = addrs; } @Override public String toString() { return "Person{" + "names=" + names + ", addrs=" + addrs + '}'; } }
<bean id="personBean" class="com.powernode.spring6.bean.Person"> <property name="names"> <!--list集合有序可重复--> <list> <value>张三</value> <value>李四</value> <value>王五</value> <value>张三</value> <value>张三</value> <value>张三</value> <value>张三</value> </list> </property> <property name="addrs"> <!--set集合无序不可重复--> <set> <value>北京大兴区</value> <value>北京大兴区</value> <value>北京海淀区</value> <value>北京海淀区</value> <value>北京大兴区</value> </set> </property> </bean>
注入Map集合与注入Properties
- Map集合:
- 使用
<map>
标签 - 如果key是简单类型,使用 key 属性,反之使用 key-ref 属性。
- 如果value是简单类型,使用 value 属性,反之使用 value-ref 属性。
- java.util.Properties继承java.util.Hashtable,所以Properties也是一个Map集合。
- Properties使用
<props>
标签嵌套<prop>
标签完成。 - 在Properties中,key和value的类型都是String类型
public class Person { // 注入Map集合 // 多个电话 private Map<Integer, String> phones; // 注入属性类对象 // Properties本质上也是一个Map集合。 // Properties的父类Hashtable,Hashtable实现了Map接口。 // 虽然这个也是一个Map集合,但是和Map的注入方式有点像,但是不同。 // Properties的key和value只能是String类型。 private Properties properties; public void setProperties(Properties properties) { this.properties = properties; } public void setPhones(Map<Integer, String> phones) { this.phones = phones; } @Override public String toString() { return "Person{" + "phones=" + phones + ", properties=" + properties + '}'; } }
<bean id="personBean" class="com.powernode.spring6.bean.Person"> <property name="properties"> <!--注入Properties属性类对象--> <props> <prop key="driver">com.mysql.cj.jdbc.Driver</prop> <prop key="url">jdbc:mysql://localhost:3306/spring6</prop> <prop key="username">root</prop> <prop key="password">123456</prop> </props> </property> <property name="phones"> <!--注入Map集合--> <map> <!--如果key和value不是简单类型就用这个配置。--> <!--<entry key-ref="" value-ref=""/>--> <!--如果是简单类型就是key和value--> <entry key="1" value="110"/> <entry key="2" value="120"/> <entry key="3" value="119"/> </map> </property> </bean>
注入null和空字符串
- 注入空字符串使用:
<value/>
或者 value=“” - 注入null使用:
<null/>
或者不为该属性赋值
public class Cat { private String name; private int age; public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Cat{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
<bean id="catBean" class="com.powernode.spring6.bean.Cat"> <!--不给属性注入,属性的默认值就是null--> <!--<property name="name" value="tom"></property>--> <!-- 这不是注入null,这只是注入了一个"null"字符串--> <!--<property name="name" value="null"/>--> <!--这种方式是手动注入null--> <!--<property name="name"> <null/> </property>--> <!--注入空字符串第一种方式--> <!--<property name="name" value=""/>--> <!--注入空字符串第二种方式--> <property name="name"> <value/> </property> <property name="age" value="3"></property> </bean>
注入的值中含有特殊符号
- XML中有5个特殊字符,分别是:<、>、'、"、&
- 以上5个特殊符号在XML中会被特殊对待,会被当做XML语法的一部分进行解析,如果这些特殊符号直接出现在注入的字符串当中,会报错。
- 解决方案包括两种:
- 第一种:特殊符号使用转义字符代替。
- 第二种:将含有特殊符号的字符串放到:
<![CDATA[]]>
当中。放在CDATA区中的数据不会被XML文件解析器解析。使用CDATA时,不能使用value属性,只能使用value标签。
- 5个特殊字符对应的转义字符分别是:
public class MathBean { private String result; public void setResult(String result) { this.result = result; } @Override public String toString() { return "MathBean{" + "result='" + result + '\'' + '}'; } }
<bean id="mathBean" class="com.powernode.spring6.bean.MathBean"> <!--第一种方案:使用实体符号代替特殊符号--> <!--<property name="result" value="2 < 3" />--> <!--第二种方案:使用<![CDATA[]]>--> <property name="result"> <!--只能使用value标签--> <value><![CDATA[2 < 3]]></value> </property> </bean>
p命名空间注入
- 目的:简化配置。
- p命名空间实际上是对set注入的简化。
- 使用p命名空间注入的前提条件包括两个:
- 第一:在XML头部信息中添加p命名空间的配置信息:
xmlns:p="http://www.springframework.org/schema/p"
- 第二:p命名空间注入是基于setter方法的,所以需要对应的属性提供setter方法。
public class Dog { // 简单类型 private String name; private int age; // 非简单类型 private Date birth; // p命名空间注入底层还是set注入,只不过p命名空间注入可以让spring配置变的更加简单。 public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public void setBirth(Date birth) { this.birth = birth; } @Override public String toString() { return "Dog{" + "name='" + name + '\'' + ", age=" + age + ", birth=" + birth + '}'; } }
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 第一步:在spring的配置文件头部添加p命名空间。 xmlns:p="http://www.springframework.org/schema/p" 第二步:使用 p:属性名 = "属性值" --> <bean id="dogBean" class="com.powernode.spring6.bean.Dog" p:name="小花" p:age="3" p:birth-ref="birthBean"/> <!--这里获取的是当前系统时间。--> <bean id="birthBean" class="java.util.Date"/> </beans>
c命名空间注入
- c命名空间是简化构造方法注入的。
- 使用c命名空间的两个前提条件:
- 第一:需要在xml配置文件头部添加c命名空间的配置信息:
xmlns:c="http://www.springframework.org/schema/c"
- 第二:需要提供构造方法。
- c命名空间是依靠构造方法的。
- 注意:不管是p命名空间还是c命名空间,注入的时候都可以注入简单类型以及非简单类型。
public class People { private String name; private int age; private boolean sex; // c命名空间是简化构造注入的。 // c命名空间注入办法是基于构造方法的。 public People(String name, int age, boolean sex) { this.name = name; this.age = age; this.sex = sex; } @Override public String toString() { return "People{" + "name='" + name + '\'' + ", age=" + age + ", sex=" + sex + '}'; } }
<?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:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 第一步:在spring的配置文件头部添加: xmlns:c="http://www.springframework.org/schema/c" 第二步:使用 c:_0 下标方式 c:name 参数名方式 --> <!--<bean id="peopleBean" class="com.powernode.spring6.bean.People" c:_0="zhangsan" c:_1="30" c:_2="true"></bean>--> <bean id="peopleBean" class="com.powernode.spring6.bean.People" c:name="jack" c:age="30" c:sex="true"></bean> </beans>
util命名空间
- 使用util命名空间可以让配置复用。
- 使用util命名空间的前提是:在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" 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">
package com.powernode.spring6.beans; import java.util.Properties; public class MyDataSource1 { // Properties属性类对象,这是一个Map集合, // key和value都是String类型。 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 + '}'; } }
<?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命名空间 在spring的配置文件头部添加: xmlns:util="http://www.springframework.org/schema/util" 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/spring6</prop> <prop key="username">root</prop> <prop key="password">123</prop> </util:properties> <!--数据源1--> <bean id="ds1" class="com.powernode.spring6.jdbc.MyDataSource1"> <property name="properties" ref="prop"/> </bean> <!--数据源2--> <bean id="ds2" class="com.powernode.spring6.jdbc.MyDataSource2"> <property name="properties" ref="prop"/> </bean> </beans>
基于 XML 的自动装配
- Spring还可以完成自动化的注入,自动化注入又被称为自动装配。
- 它可以根据名字进行自动装配,也可以根据类型进行自动装配。
根据名称自动装配
- 如果根据名称装配(byName),底层会调用set方法进行注入。
- 例如:setAge() 对应的名字是age,setPassword()对应的名字是password,setEmail()对应的名字是email。
public class OrderDao { private static final Logger logger = LoggerFactory.getLogger(OrderDao.class); public void insert(){ logger.info("订单正在生成...."); } }
public class OrderService { private OrderDao orderDao; // 通过set方法给属性赋值。 public void setOrderDao(OrderDao orderDao) { this.orderDao = orderDao; } /** * 生成订单的业务方法。。。 */ public void generate(){ orderDao.insert(); } }
<!--根据名字进行自动装配--> <!--注意:自动装配也是基于set方式实现的。--> <bean id="orderService" class="com.powernode.spring6.service.OrderService" autowire="byName"></bean> <!--id一般也叫作bean的名称。--> <!--根据名字进行自动装配的时候,被注入的对象的bean的id不能随便写, set方法的方法名去掉set,剩下单词首字母小写。--> <bean id="orderDao" class="com.powernode.spring6.dao.OrderDao"/>
- OrderService Bean中需要添加autowire=“byName”,表示通过名称自动进行装配。
- OrderService 类中有一个OrderDao属性,而OrderDao属性的名字是orderDao,对应的set方法是setOrderDao(),正好和OrderDao Bean的id是一样的,可以根据名称自动装配。
根据类型自动装配
- 无论是byName还是byType,在装配的时候都是基于set方法的,所以set方法是必须要提供的,提供构造方法是不行的
- 如果byType,根据类型装配时,如果配置文件中有两个类型一样的bean会报错
- 当byType进行自动装配的时候,配置文件中某种类型的Bean必须是唯一的,不能出现多个。
- 如果存在多个类型一样的Bean,则Spring会不知道使用那个Bean进行注入
public class CustomerService { private UserDao userDao; private VipDao vipDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void setVipDao(VipDao vipDao) { this.vipDao = vipDao; } public void save(){ userDao.insert(); vipDao.insert(); } }
<!--根据类型进行自动装配--> <!--自动装配是基于set方法的--> <!--根据类型进行自动装配的时候,在有效的配置文件当中,某种类型的实例只能有一个。--> <bean class="com.powernode.spring6.dao.VipDao"></bean> <bean id="x" class="com.powernode.spring6.dao.UserDao"></bean> <!--如果byType,根据类型装配时,如果配置文件中有两个类型一样的bean会报错--> <!--<bean id="y" class="com.powernode.spring6.dao.UserDao"></bean>--> <bean id="cs" class="com.powernode.spring6.service.CustomerService" autowire="byType"></bean>
Spring引入外部属性配置文件
- 我们都知道编写数据源的时候是需要连接数据库的信息的,例如:driver url username password等信息。这些信息可以单独写到一个属性配置文件中吗,这样用户修改起来会更加的方便
jdbc.driverClass=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/spring6 jdbc.username=root jdbc.password=123
<?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"> <!-- 引入外部的properties文件 第一步:引入context命名空间。 xmlns:context="http://www.springframework.org/schema/context" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 第二步:使用标签context:property-placeholder的location属性来指定属性配置文件的路径。 location默认从类的根路径下开始加载资源。 --> <context:property-placeholder location="jdbc.properties"/> <!--配置数据源--> <bean id="ds" class="com.powernode.spring6.jdbc.MyDataSource"> <!--怎么取值呢?第三步:${key}--> <property name="driver" value="${jdbc.driverClass}"></property> <property name="url" value="${jdbc.url}"></property> <!--加前缀是由于spring加载变量是优先从系统变量中进行加载,username系统变量已经存在--> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> </beans>