自动装配有几种?
在Spring框架,可以用 auto-wiring 功能会自动装配Bean。要启用它,只需要在 < bean>定义“autowire”属性。
< bean id=“customer” class=“com.jkk.common” autowire=“byName” />
在Spring中,支持 5 自动装配模式。
- no – 缺省情况下,自动配置是通过“ref”属性手动设定
< property name=“person” ref=“person” />
-
byName – 根据属性名称自动装配。如果一个bean的名称和其他bean属性的名称是一样的,将会自装配它。依靠set方法
-
byType – 按数据类型自动装配。如果一个bean的数据类型是用其它bean属性的数据类型,兼容并 自动装配它。依靠set方法
-
constructor – 在构造函数参数的byType方式。
-
autodetect – 如果找到默认的构造函数,使用“自动装配用构造”; 否则,使用“按类型自动装配”。
类型(Type)自动装配
(类型相同,id-名字不同的定义多个会报错)
- Beans
两个Bean,person 和 ability.
package com.bai.common;
public class Person
{
private Ability ability;
//...
}
package com.bai.common;
public class Ability
{
private String skill;
//...
}
-
Spring Wiring
通常情况下,明确地装配 bean:
<bean id="person" class="com.bai.common.Person">
<property name="ability" ref="invisible" />
</bean>
<bean id="invisible" class="com.bai.common.Ability" >
<property name="skill" value="Invisible" />
</bean>
输出
Person [ability=Ability [skill=Invisible]]
随着自动装配按类型启用后,可以保留ability属性未设置。Spring会发现相同的数据类型并自动装配它。
<bean id="person" class="com.bai.common.Person" autowire="byType" />
<bean id="invisible" class="com.bai.common.Ability" >
<property name="skill" value="Invisible" />
</bean>
输出
Person [ability=Ability [skill=Invisible]]
如果你有两个Bean,都是类“ability”相同的数据类型?
被报错
<bean id="person" class="com.bai.common.Person" autowire="byType" />
<bean id="steal" class="com.bai.common.Ability" >
<property name="skill" value="Steal" />
</bean>
<bean id="invisible" class="com.bai.common.Ability" >
<property name="skill" value="Invisible" />
</bean>
输出
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException:
...
No unique bean of type [com.yiibai.common.Ability] is defined:
expected single matching bean but found 2: [steal, invisible]; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [com.yiibai.common.Ability] is defined:
expected single matching bean but found 2: [steal, invisible]
在这种情况下,它会打出 UnsatisfiedDependencyException (未满足依赖)的错误消息。
注:在类型的自动装配模式,就必须确保只有Bean 只有一个唯一的数据类型声明
名称(Name)自动装配
如果一个bean的名称与其他bean属性的名称是一样的,那么将自动装配它。
-
Beans
这里有两个 beans, 分别是:customer 和 address.
package com.common;
public class Customer
{
private Address address;
//...
}
package com.common;
public class Address
{
private String fulladdress;
//...
}
- Spring 装配
通常情况下,您明确装配Bean,这样通过 ref 属性:
<bean id="customer" class="com.common.Customer" >
<property name="address" ref="address" />
</bean>
<bean id="address" class="com.common.Address" >
<property name="fulladdress" value="YiLong Road, CA 188" /> </bean>
输出
Customer [address=Address [fulladdress=YiLong Road, CA 188]]
使用按名称启用自动装配,你不必再声明属性标记。只要在“address” bean是相同于“customer” bean 的“address”属性名称,Spring会自动装配它。
<bean id="customer" class="com.common.Customer" autowire="byName" />
<bean id="address" class="com.common.Address" >
<property name="fulladdress" value="YiLong Road, CA 188" /> </bean>
输出
Customer [address=Address [fulladdress=YiLong Road, CA 188]]
看看下面另一个例子,这一次,装配将会失败,导致bean “addressABC”不匹配“customer” bean的属性名称。
<bean id="customer" class="com.common.Customer" autowire="byName" />
<bean id="addressABC" class="com.common.Address" >
<property name="fulladdress" value="Block A 888, CA" />
</bean>
输出
Customer [address=null]
Spring由构造方法自动装配
- Beans
这里有两个 beans, 分别是:developer 和 language
package com.common;
public class Developer {
private Language language;
public Developer(Language language) {
this.language = language;
}
//...
}
package com.common;
public class Language {
private String name;
//...
}
-
Spring装配
通常情况下,你可以通过构造这样自动装配 Bean:
<bean id="developer" class="com.common.Developer">
<constructor-arg>
<ref bean="language" />
</constructor-arg>
</bean>
<bean id="language" class="com.common.Language" >
<property name="name" value="Java" />
</bean>
输出
Developer [language=Language [name=Java]]
随着自动装配用构造函数启用后,你可以不设置构造器属性。Spring会找到兼容的数据类型,并自动装配它。
<bean id="developer" class="com..common.Developer" autowire="constructor" />
<bean id="language" class="com.common.Language" >
<property name="name" value="Java" />
</bean>
输出
Developer [language=Language [name=Java]]
Spring使用@Autowired注解自动装配
启用@Autowired,
必须注册“AutowiredAnnotationBeanPostProcessor’,
- < context:annotation-config />
添加 Spring 上下文和< context:annotation-config />在bean配置文件中。
<beans
//...
xmlns:context="http://www.springframework.org/schema/context"
//...
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
//...
<context:annotation-config />
//...
</beans>
完整版applicationContext.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!-- 开启注解 -->
<context:annotation-config />
<!-- 自动扫描(service),(dao) -->
<context:component-scan base-package="com.gx.dao,com.gx.service">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service" />
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" />
</context:component-scan>
</beans>
@Autowired示例
- @Autowired setter 方法
public class Customer
{
private Person person;
private int type;
private String action;
//getter and setter methods
@Autowired
public void setPerson(Person person) {
this.person = person;
}
}
- @Autowired 构造方法
public class Customer
{
private Person person;
private int type;
private String action;
//getter and setter methods
@Autowired
public Customer(Person person) {
this.person = person;
}
}
- @Autowired 字段
import org.springframework.beans.factory.annotation.Autowired;
public class Customer
{
@Autowired
private Person person;
private int type;
private String action;
//getter and setter methods
}
上面的例子会自动装配“PersonBean”到Customer的person属性。
执行它
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App
{
public static void main( String[] args )
{
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"});
Customer cust = (Customer)context.getBean("CustomerBean");
System.out.println(cust);
}
}
输出
Customer [person=Person [name=YiibaiA], type=1, action=buy]
依赖检查
当Spring无法找到匹配的Bean装配,它会抛出异常。
可以通过 @Autowired 的“required”属性设置为false来禁用此检查功能。
@Autowired(required=false)
private Person person;
@Qualifier
@Qualifier注解我们用来控制bean应在字段上自动装配。
@Autowired
@Qualifier(“personA”)
private Person person;
<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-2.5.xsd">
<bean
class ="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<bean id="customer" class="com..common.Customer" />
<bean id="personA" class="com.common.Person" >
<property name="name" value="yiibaiA" />
</bean>
<bean id="personB" class="com.common.Person" >
<property name="name" value="yiibaiB" />
</bean>
</beans>