自动装配是什么?
自动装配就是让应用上下文为用户找到依赖项的过程,就是Sping会在上下文中自动查找,并自动给bean装配与其关联的属性。
spring中实现自动装配的方式有两种,一种是xml文件,另有一种是通过注解。
手动装配
通过xml配置文件实现自动装配
我们只需要在bean的配置文件中的bean标签中加入一个属性autowire即可.
使用autowire关键字声明bean的自动装配方式,其可选值为byName,byType,constructor,default,no。
1.byName
设置autowire属性为byName实现进行自动装配,此时spring将会尝试将属性名和bean名称进行匹配,如果找到的话就注入依赖。
autowire=ByName进行自动装配的时候,spring容器将会检查需要注意依赖的bean中依赖名称,当存在依赖的名称时候就会对应得bean注入进去。
//Cat
package org.example;
public class Cat {
}
//Dog
package org.example;
public class Dog {
}
// People
package org.example;
public class People {
private String name;
private Cat cat;
private Dog dog;
public void getName() {
System.out.println("People的名字:"+name);
}
public void setName(String name) {
this.name = name;
}
public void getCat() {
System.out.println("People的猫:"+cat);
}
public void setCat(Cat cat) {
this.cat = cat;
}
public void getDog() {
System.out.println("People的狗:"+dog);
}
public void setDog(Dog dog) {
this.dog = dog;
}
}
bean,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 https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="cat" class="org.example.Cat"/>
<bean id="dog" class="org.example.Dog"/>
<bean id="people" class="org.example.People">
<property name="name" value="张三"/>
<property name="cat" ref="cat"/>
<property name="dog" ref="dog"/>
</bean></beans>
运行结果:
注意:
**需要注意的是:如果spring容器中没有找到对应名称可以注入的bean,将不会向依赖中注入任何bean,此时依赖的bean为null.
2.byType
在byType(类型模式中)spring容器会基于反射查看bean定义的类,然后找到依赖类型相同的bean注入到另外的bean中,这个过程需要setter注入来完成,因此必须存在setter方法,否则就会注入失败
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="cat" class="org.example.Cat"/>
<bean id="dog" class="org.example.Dog"/>
<bean id="people" class="org.example.People" autowire="byType">
<property name="name" value="张三"></property>
</bean>
</beans>
运行结果
注意:
使用byType这种方式,必须保证配置文件中所有bean的class属性的值是唯一的,否则就会报错
By constructor构造器
使用autowire=constructor的时候,spring容器同样会尝试找到那些类型与构造函数相匹配的bean,然后注入.
autowire=constructor模式下,spring容器会找到类型和构造函数中的类型相匹配的bean,然后注入。
在实际测试开发中当spring容器中出现多个类型和构造函数中的类型相匹配的bean,那么bean的名称和要依赖的名称相同的将会注入进去,会自动将同类不同名的bean过滤掉,如果只有一个bean,类名相同但是名称不同,也会将这个注入到该类中,如果有两个以上bean,类名相同,但是名称不同,这个时候spring容器不知道选择哪一个bean,需要使用autowire-candidate="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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
注意:
conteext:annotation-config/ 必须要写在xml中,这是用来开启注解的支持,如果不加上注解就无效。
使用
Autowired注解(常用)
然后在实体类的对应属性上添加@Autowired注解(也可以把注解放到对应属性的setter上),people类中依赖Dog类和Cat类。所以在people类中的dog和cat属性上要加上@Autowired,实现自动装配。使用@Autowired注释,可以对成员变量,方法以及构造函数进行标注,完成自动装配的工作。**通过@Autowired的使用标注到成员变量的时候不需要有set方法,Autowired是按照默认类型匹配的.
在使用@Autowired的时候还传递了一个required=fale属性,required属性为false表示userDao实例存在就进行注入不存在的话就忽略,如果required=true,表示必须要进行注入,如果userDao实例不存在就抛出异常。默认情况下@Autowired是按照类型匹配的,如果需要按照名称进行匹配的话,可以使用@Qualifier注解和@Autowired相结合的方式
首先要配置bean.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean id="cat02" class="org.example.Cat"/>
<bean id="dog02" class="org.example.Dog"/>
<bean id="people02" class="org.example.People02">
<property name="name" value="张三"/>
</bean>
</beans>
//people类
package org.example;
import org.springframework.beans.factory.annotation.Autowired;
public class People02 {
private String name;
@Autowired(required = false)
// @Qualifier("cat02")
private Cat cat;
@Autowired(required = false)
// @Qualifier("dog02")
private Dog dog;
public void getName() {
System.out.println("People的name:"+name);
}
public void setName(String name) {
this.name = name;
}
public void getCat() {
System.out.println("People的Cat:"+cat);
}
public void setCat(Cat cat) {
this.cat = cat;
}
public void getDog() {
System.out.println("People的Dog:"+dog);
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "People02{" +
"name='" + name + '\'' +
", cat=" + cat +
", dog=" + dog +
'}';
}
}
运行结果:
测试代码:
//PeopleTest01
import org.example.People;
import org.example.People02;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;
public class PeopleTest01 {
@Test
public void Test01(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean03.xml");
People people =(People) context.getBean("people");
people.getName();
people.getCat();
people.getDog();
}
@Test
public void Test02(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean04.xml");
People people = (People) context.getBean("people");
people.getName();
people.getCat();
people.getDog();
}
@Test
public void Test03(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean08.xml");
People02 people = (People02) context.getBean("people02");
people.getName();
people.getCat();
people.getDog();
System.out.println(people);
}
}
Resource
与@Autowired具备相同效果的是@Resource,@Resource默认使用的是byName的方式进行注入,**使用之前要导入Resource包:Package:javax.annotation.Resource,**可以标注在成员变量和set方法上,但是不能放在构造方法上面,@Resource有两个重要的属性:name type ,spring容器会解析@Resource注解的name属性为bean的名字,type属性为bean的类型,使用@Resource注解的name属性表示按照byName进行解析,使用type属性表示按照byType类型进行解析,不指定的时候默认使用name。
Value
@Autowired和@Resource进行自动装配注入的依赖都是对象类型,而不是简单的值类型,之前使用配置文件的setter和构造函数的时候可以通过property属性和constructor-arg属性既可以注入对象类型也可以注入简单值类型,对于这些类型,比如 int boolean long String 等等,spring容器提供了@Value注解的注入方式,@Value注解接收一个String的值,该值指定了要注入到 内置的java类型 的属性值(不用担心类型转换),一般情况下@Value属性和properties文件配合使用,分为两种情况,一种是SpEL(类似于js中的EL表达式),一种是占位符方式.
实例:
bean.xml
<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"
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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!--基于占位符方式 配置单个properties -->
<!--<context:property-placeholder location="jdbc.properties"/>-->
<!--基于占位符方式 配置多个properties -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
<property name="location" value="jdbc.properties"/>
</bean>
<!--基于SpEL表达式 配置多个properties id值为configProperties 提供java代码中使用 -->
<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:/jdbc.properties</value>
</list>
</property>
</bean>
<!--基于SpEL表达式 配置单个properties -->
<!--<util:properties id="configProperties" location="classpath:jdbc.properties"/>-->
<!--注解驱动 -->
<context:annotation-config/>
<bean id="people03" class="org.example.People02" ></bean>
<bean id="jdbcTest01" class="org.example.JDBCTest01"></bean>
</beans>
//JDBCTest01
package org.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
public class JDBCTest01 {
// 注册成员变量
@Autowired
@Qualifier("people03")
private People02 people;
// 占位符方式
@Value("${url}")
private String url;
// SpEL表达方式
@Value("#{configProperties['user']}")
private String username;
@Value("#{configProperties['password']}")
private String password;
@Value("#{configProperties['driver']}")
private String driver;
public void done(){
System.out.println("URL:"+url+"\nUsername:"+username+"\nPassword"+password+"\nDriver:"+driver);
}
}
测试:
import org.example.JDBCTest01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;
public class ValueTest01 {
@Test
public void Test01(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean09.xml");
JDBCTest01 jdbcTest01 =(JDBCTest01) context.getBean("jdbcTest01");
jdbcTest01.done();
}
}
运行结果: