1. p命名空间注入 31
目的:简化配置。
使用p命名空间注入的前提条件包括两个:
● 第一:在XML头部信息中添加p命名空间的配置信息:xmlns:p="http://www.springframework.org/schema/p"
● 第二:p命名空间注入是基于setter方法的,所以需要对应的属性提供setter方法。
package com.powernode.spring6.bean;
import java.util.Date;
/**
* p命名空间注入 31
**/
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 () {
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">
<!-- p命名空间注入 31-->
<!--
第一步:在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>
//p命名空间注入 31
@Test
public void testP(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-p.xml");
Dog dogBean = applicationContext.getBean("dogBean", Dog.class);
System.out.println(dogBean);
}
把setter方法去掉:
所以p命名空间实际上是对set注入的简化。
2. c命名空间注入 32
c命名空间是简化构造方法注入的。
使用c命名空间的两个前提条件:
第一:需要在xml配置文件头部添加信息:xmlns:c="http://www.springframework.org/schema/c"
第二:需要提供构造方法。
package com.powernode.spring6.bean;
/**
* c命名空间注入 32
**/
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 () {
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">
<!-- c命名空间注入 32-->
<!--
第一步:在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>
// c命名空间注入 32
@Test
public void testC(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-c.xml");
People peopleBean = applicationContext.getBean("peopleBean", People.class);
System.out.println(peopleBean);
}
把构造方法注释掉:
所以,c命名空间是依靠构造方法的。
注意:不管是p命名空间还是c命名空间,注入的时候都可以注入简单类型以及非简单类型。
3. util命名空间注入 33
使用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.jdbc;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Properties;
import java.util.logging.Logger;
/**
* util命名空间注入 33
**/
public class MyDataSource1 implements DataSource {
// 连接数据库的信息
/*private String driver;
private String url;
private String username;
private String password;*/
// Properties属性类对象,底层一个Map集合,key和value都是String类型。
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "MyDataSource1{" +
"properties=" + properties +
'}';
}
@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 unwrap(Class iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class iface) throws SQLException {
return false;
}
}
package com.powernode.spring6.jdbc;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Properties;
import java.util.logging.Logger;
/**
* util命名空间注入 33
**/
public class MyDataSource2 implements DataSource {
// Properties属性类对象,底层一个Map集合,key和value都是String类型。
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "MyDataSource1{" +
"properties=" + properties +
'}';
}
@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 unwrap(Class iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class iface) throws SQLException {
return false;
}
}
<?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命名空间注入 33-->
<!--引入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>
//util命名空间注入 33
@Test
public void testUtil(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-util.xml");
MyDataSource1 ds1 = applicationContext.getBean("ds1", MyDataSource1.class);
MyDataSource2 ds2 = applicationContext.getBean("ds2", MyDataSource2.class);
System.out.println(ds1);
System.out.println(ds2);
}
4. 基于XML的自动装配 34
Spring还可以完成自动化的注入,自动化注入又被称为自动装配。它可以根据名字进行自动装配,也可以根据类型进行自动装配。
4.1 根据名称自动装配 34
根据名字进行自动装配的时候,被注入的对象的bean的id不能随便写,
怎么写?set方法的方法名去掉set,剩下单词首字母小写。
举例
这说明,如果根据名称装配(byName),底层会调用set方法进行注入。
例如:setAge() 对应的名字是age,setPassword()对应的名字是password,setEmail()对应的名字是email。
<!-- 根据名称自动装配 34-->
<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"/>
//根据名称自动装配 34
@Test
public void testAutowire(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-autowire.xml");
OrderService orderService = applicationContext.getBean("orderService", OrderService.class);
orderService.generate();
// CustomerService cs = applicationContext.getBean("cs", CustomerService.class);
// cs.save();
}
4.2 根据类型自动装配 35
<!-- 根据类型自动装配 35-->
<!--自动装配是基于set方法的-->
<!--根据类型进行自动装配的时候,在有效的配置文件当中,某种类型的实例只能有一个。-->
<bean class="com.powernode.spring6.dao.VipDao"></bean>
<bean id="x" class="com.powernode.spring6.dao.UserDao"></bean>
<!--<bean id="y" class="com.powernode.spring6.dao.UserDao"></bean>-->
<bean id="cs" class="com.powernode.spring6.service.CustomerService" autowire="byType"></bean>
//根据名称和类型自动装配 34
@Test
public void testAutowire(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-autowire.xml");
//根据名称自动装配 35
// OrderService orderService = applicationContext.getBean("orderService", OrderService.class);
// orderService.generate();
//根据类型自动装配 35
CustomerService cs = applicationContext.getBean("cs", CustomerService.class);
cs.save();
}
我们把CustomerService中的set方法注释掉,再执行
可以看到无论是byName还是byType,在装配的时候都是基于set方法的。所以set方法是必须要提供的。提供构造方法是不行的,大家可以测试一下。这里就不再赘述。
如果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必须是唯一的,不能出现多个。
5. spring引入外部属性配置文件 36
我们都知道编写数据源的时候是需要连接数据库的信息的,例如:driver url username password等信息。这些信息可以单独写到一个属性配置文件中吗,这样用户修改起来会更加的方便。当然可以。
第一步:写一个数据源类,提供相关属性。
package com.powernode.spring6.jdbc;
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;
// 简单类型在实际开发中的应用 24
//所有的数据源都要实现java规范:javax.sql.DataSource
//什么是数据源:能够给你提供Connection对象的,都是数据源。
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 24
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 unwrap(Class iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class iface) throws SQLException {
return false;
}
}
第二步:在类路径下新建jdbc.properties文件,并配置信息。
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring6
jdbc.username=root
jdbc.password=123
第三步:在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>
第四步:在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">
<!--
spring引入外部属性配置文件 36
引入外部的properties文件
第一步:引入context命名空间。
第二步:使用标签context:property-placeholder的location属性来指定属性配置文件的路径。
location默认从类的根路径下开始加载资源。
-->
<context:property-placeholder location="jdbc.properties"/>
<bean id="ds" class="com.powernode.spring6.jdbc.MyDataSource">
<property name="driver" value="${jdbc.driverClass}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
</beans>
测试
//spring引入外部属性配置文件 36
@Test
public void testProperties(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-properties.xml");
MyDataSource ds = applicationContext.getBean("ds", MyDataSource.class);
System.out.println(ds);
}
代码汇总
全部在course5中