De acordo com o último tutorial da estrutura Spring do [Power Node], o primeiro conjunto de tutoriais Spring6 em toda a rede, segui Lao Du desde a primavera de aprendizado zero até o avançado e as notas originais de Lao Du https://www.yuque.com/ docs/share/866abad4-7106 -45e7-afcd-245a733b073f?# "Spring6" está organizado, senha do documento: mg9b
Os artigos relacionados à primavera são compilados e resumidos em: https://www.yuque.com/u27599042/zuisie
definir tópico de injeção
Injetar beans externos
- Bean Externo: O bean a ser injetado é definido fora do bean que precisa ser injetado
- Para beans externos, use o atributo ref na tag de propriedade para injeção, ou use a tag ref para injeção. A injeção através do atributo ref é comumente usada.
<!--声明/定义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>
Injetar beans internos
- Bean Interno: Aninhe a tag do bean na tag do bean, ou seja, o bean que precisa ser injetado é declarado no bean que precisa ser injetado através da tag do bean, e então injetado diretamente no bean que precisa ser injetado.
<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>
Injetar tipos simples
- Se estiver atribuindo um valor a um tipo simples, ou seja, injetando um tipo simples em uma propriedade, use o atributo value ou a tag value em vez de 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>
Tipos simples no Spring
- De acordo com a análise do código-fonte da classe BeanUtils, os tipos simples incluem:
- tipo de dados básico
- Classe de empacotamento correspondente ao tipo de dados básico
- String ou outra subclasse CharSequence
- Subclasse de número
- Subclasse de data, java.util.Date é um tipo simples
- Subclasse de enumeração
- URI
- URL
- Subclasse temporal, Temporal é o tipo de horário e fuso horário fornecido pelo Java8
- Locale, Locale é uma classe de linguagem e um tipo simples.
- Aula
- Além disso, os tipos de array correspondentes aos tipos de valor simples acima também estão incluídos.
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));
}
//........
}
Teste todos os tipos simples
- Escreva um programa que teste todos os tipos simples:
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
}
- você precisa estar ciente é:
- Se Date for considerado um tipo simples, o formato da string de data não pode ser escrito casualmente. O formato deve estar em conformidade com o formato do método toString() de Date. Obviamente, isso é de mau gosto. Se fornecermos uma string de data como esta: 11/10/2010, ela não poderá ser atribuída a um atributo do tipo Data.
- Após o spring6, quando uma URL é injetada, a validade da string da URL será verificada. Se for um URL existente, tudo bem. Relata um erro se ele não existir.
Caso clássico de injeção de tipos simples
- Caso clássico: injetar valores em atributos da fonte de dados:
- Suponha que agora queiramos escrever uma fonte de dados à mão. Todos sabemos que todas as fontes de dados devem implementar a interface javax.sql.DataSource, e a fonte de dados deve ter informações para se conectar ao banco de dados, como: driver, url, nome de usuário , senha, etc.
- Fonte de dados: todas as fontes de dados podem fornecer objetos 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);
}
Atribuição de propriedade em cascata
// 班级类
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 +
'}';
}
}
- Método de injeção original
<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>
- Injeção em cascata:
- Nota: Para atribuição de atributos em cascata, o método get deve ser fornecido para variáveis de membro que fazem referência a outros objetos, porque ao executar a atribuição de atributos em cascata, você precisa primeiro chamar o método get para obter as variáveis de membro que fazem referência a outros objetos e, em seguida, chamar o variável de membro.Método de conjunto de atributos para atribuição de atributos
<!--使用级联属性赋值需要注意两点:
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>
Injetar na matriz
Os elementos da matriz são tipos simples
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>
Os elementos da matriz são do tipo não simples
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>
Resumo da injeção de arrays
- Se a matriz contiver tipos simples, use a tag value.
- Se a matriz contiver tipos não simples, use a tag ref.
Coleção de lista de injeção e coleção de conjunto
- Coleção de listas: ordenada e repetível
- Nota: Use a tag list ao injetar na coleção List. Se a coleção List for do tipo simples, use a tag value. Caso contrário, use a tag ref.
- Coleção de conjuntos: não ordenada e não repetível
- Pontos principais: Use tags ao injetar coleções de conjuntos
<set>
. Se os elementos na coleção de conjuntos forem de tipos simples, use a tag value. Caso contrário, use a tag ref.
- Pontos principais: Use tags ao injetar coleções de conjuntos
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>
Injetar coleção de mapas e injetar propriedades
- Coleção de mapas:
- Usar
<map>
tags - Se a chave for de um tipo simples, use o atributo key, caso contrário, use o atributo key-ref.
- Se value for um tipo simples, use o atributo value, caso contrário, use o atributo value-ref.
- Usar
- java.util.Properties herda java.util.Hashtable, então Properties também é uma coleção de mapas.
- As propriedades são feitas usando
<props>
tags aninhadas dentro<prop>
de tags. - Em Propriedades, os tipos chave e valor são ambos tipos String.
- As propriedades são feitas usando
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>
Injetar strings nulas e vazias
- Para injetar uma string vazia use:
<value/>
ou value="" - Injete nulo usando:
<null/>
ou não atribua um valor à propriedade
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>
O valor injetado contém símbolos especiais
- Existem 5 caracteres especiais em XML, a saber: <, >, ', ", &
- Os cinco símbolos especiais acima serão tratados especialmente em XML e serão analisados como parte da sintaxe XML.Se estes símbolos especiais aparecerem directamente na string injectada,será reportado um erro.
- Existem duas soluções:
- Tipo 1: Use caracteres de escape para substituir símbolos especiais.
- O segundo tipo: coloque a string contendo símbolos especiais em
<![CDATA[]]>
:. Os dados colocados em uma seção CDATA não serão analisados por um analisador de arquivo XML. Ao usar CDATA, você não pode usar o atributo value, apenas a tag value.
- Os caracteres de escape correspondentes aos 5 caracteres especiais são:
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>
injeção de namespace p
- Objetivo: Simplificar a configuração.
- O namespace p é na verdade uma simplificação da injeção de conjunto.
- Os pré-requisitos para usar a injeção de namespace p incluem dois:
- Primeiro: adicione as informações de configuração do namespace p nas informações do cabeçalho XML:
xmlns:p="http://www.springframework.org/schema/p"
- Segundo: a injeção de namespace p é baseada no método setter, portanto, o atributo correspondente precisa fornecer um método setter.
- Primeiro: adicione as informações de configuração do namespace p nas informações do cabeçalho XML:
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 injeção de namespace
- O namespace c é injetado pelo construtor simplificado.
- Dois pré-requisitos para usar o namespace c:
- Primeiro: as informações de configuração do namespace c precisam ser adicionadas ao cabeçalho do arquivo de configuração xml:
xmlns:c="http://www.springframework.org/schema/c"
- Segundo: métodos de construção precisam ser fornecidos.
- Primeiro: as informações de configuração do namespace c precisam ser adicionadas ao cabeçalho do arquivo de configuração xml:
- O namespace c depende do construtor.
- Nota: Independentemente do namespace p ou do namespace c, tipos simples e tipos não simples podem ser injetados durante a injeção.
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>
namespace do utilitário
- Usar o namespace util permite a reutilização da configuração.
- O pré-requisito para usar o namespace util é adicionar informações de configuração ao cabeçalho do arquivo de configuração do Spring.
- do seguinte modo:
<?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>
Autowiring baseado em XML
- A mola também pode completar a injeção automatizada, também chamada de montagem automática.
- Ele pode ser montado automaticamente com base no nome ou montado automaticamente com base no tipo.
Monte automaticamente com base no nome
- Se montado com base no nome (byName), a camada inferior chamará o método set para injeção.
- Por exemplo: o nome correspondente de setAge() é idade, o nome correspondente de setPassword() é senha e o nome correspondente de 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"/>
- Autowire="byName" precisa ser adicionado ao Bean OrderService, o que significa montagem automática por nome.
- Existe um atributo OrderDao na classe OrderService, e o nome do atributo OrderDao é orderDao, e o método set correspondente é setOrderDao(), que é exatamente igual ao id do Bean OrderDao e pode ser montado automaticamente de acordo com o nome.
Montagem automática baseada no tipo
- Seja byName ou byType, eles são baseados no método set durante a montagem, portanto, o método set deve ser fornecido e não é possível fornecer um método construtor.
- Se byType, ao montar por tipo, houver dois beans do mesmo tipo no arquivo de configuração, será reportado um erro.
- Quando byType realiza montagem automática, um determinado tipo de Bean no arquivo de configuração deve ser único e não pode aparecer como múltiplo.
- Se houver vários beans do mesmo tipo, o Spring não saberá qual bean usar para injeção.
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 introduz arquivos de configuração de propriedades externas
- Todos sabemos que ao escrever uma fonte de dados, precisamos de informações para nos conectarmos ao banco de dados, como: url do driver, nome de usuário, senha e outras informações. Essas informações podem ser gravadas separadamente em um arquivo de configuração de propriedades, para que seja mais conveniente para os usuários modificá-las?
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>