自动装配(autowiring):有助于减小甚至消除配置<property>元素和<constructor-arg>元素,让Spring自动识别如何装配Bean的依赖关系。java
自动检测(autodiscovery):比自动装配更进一步,让Spring可以自动识别哪些类须要被配置成Spring Bean,从而减小对<bean>元素的使用。正则表达式
byName——把与Bean的属性具备相同名字(或者ID)的其余Bean自动装配到Bean的对应属性中。若是没有跟属性的名字相匹配的Bean,则该属性不进行装配。spring
byType——把与Bean的属性具备相同类型的其余Bean自动装配到Bean的对应属性中。若是没有跟属性的名字相匹配的Bean,则该属性不进行装配。express
constructor——把与Bean的构造器入参具备相同类型的其余Bean自动装配到Bean构造器的对应入参中。ui
autodetect——首先尝试使用constructor进行自动装配。若是失败,再尝试使用byType进行自动装配。spa
byName自动装配code
——为属性自动装配ID与该属性同名的Beancomponent
例:xml
假设存在一个Instrumentalist类包含属性song、instrument,如下是手动装配Bean的方式。对象
<bean id="saxophone" class="com.roger.spring.beans.Saxophone" /> <bean id="kenny" class="com.roger.spring.beans.Instrumentalist"> <property name="song" value="Jingle Bells" /> <property name="instrument" ref="saxophone" /> </bean>
若是要利用byName自动装配,就须要在使用<bean>元素定义Saxophone的时候,将Bean的id设置为I和nstrumentalist属性instrument同名的字面值。 经过配置autowire属性就能够利用此信息自动装配 kenny 的 instrument 属性了。
<bean id="instrument" class="com.roger.spring.beans.Saxophone" /> <bean id="kenny" class="com.roger.spring.beans.Instrumentalist" autowire="byName"> <property name="song" value="Jingle Bells" /> </bean>
byType自动装配
——Spring会寻找哪个Bean的类型与属性的类型相同。
局限:若是Spring寻找到多个Bean,它们的类型与须要自动装配的属性的类型都相匹配,这时候,Spring不会猜想哪个Bean更适合自动装配,而是选择抛出异常。因此,应用只容许存在一个Bean与须要自动装配的属性类型相匹配。
解决装配歧义的问题:能够为自动装配标识一个首选,或者取消某个Bean自动装配的候选资格。
标识首选
利用<bean>的primary属性, 默认为true,所以要达到标识首选的目的,须要将其余候选的primary属性都设为false。
取消候选
将<bean>的autowire-candidate属性设为false。
constructor自动装配
——在Bean声明中,不须要<constructor-arg>元素了
局限:a. 具备和byType自动装配相同的局限,当发现多个Bean匹配某个构造器入参时,Spring不会猜想哪一个更适合;
b. 若是一个类有多个构造器,它们都知足自动装配的条件时,Spring也会猜想哪一个更适合。
默认自动装配
利用<beans>属性default-autowire进行设置,默认为none,表示都不使用自动装配。能够利用<bean>元素的autowire属性来覆盖<beans>的默认自动装配策略。
使用注解方式容许更细粒度的自动装配,能够选择性地标注某一个属性来对其应用自动装配。
Spring容器默认禁用注解装配
xml配置中启用注解,利用context命名空间中<context:annotation-config>元素,以下所示:
<?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"> <context:annotation-config /> </beans>
Spring支持集中不一样的用于自动装配的注解:
Spring自带的@Autowired注解
JSR-330的@Inject注解
JSR-250的@Resource注解
@Autowired 默认是经过byType方式进行自动装配的,经过结合@Qualifier注解能够经过匹配Bean的id进行自动装配。
如:
经过@Qualifier注解将范围缩小,尝试将id为"guita"的bean注入。
@Autowired @Qualifier("guita") private Instrument instrument;
a、@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;
b、@Autowired默认是按照类型装配注入的,若是想按照名称来转配注入,则须要结合@Qualifier一块儿使用;
c、@Resource注解是由J2EE提供,而@Autowired是由Spring提供,故减小系统对spring的依赖建议使用
@Resource的方式;
d、@Resource和@Autowired均可以书写标注在字段或者该字段的setter方法之上
即便<context:annotation-config>元素有助于彻底消除Spring配置中的<property>和<constructor-arg>元素,可是仍要使用<bean>元素显示定义Bean。
所以,借助<context:component-scan>元素,除了完成与<context:annotation-config>同样的工做,还容许Spring自动检测Bean和定义Bean。中意味着不使用<bean>元素,Spring应用中的大多数(或全部)Bean都可以实现定义和装配。
还能够经过<context:component-scan>元素的base-package属性标识<context:component-scan>元素会扫描指定的包及其全部子包。
<?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"> <context:component-scan base-package="com.roger.spring.beans"> </context:component-scan> </beans>
默认状况下,<context:component-scan>查找使用构造型(stereotype)注解所标注的类。
这些特殊注解以下:
@Component——经过的构造型注解,标识该类为Spring组件
@Controller——标识将该类定义为Spring MVC controller
@Repository——标识将该类定义为数据仓库
@Service——标识将该类定义为服务
使用@Component标注的任意自定义注解
Spring扫描发现@Component注解所标注的类,并自动地将它注册为Spring Bean,Bean的ID默认为无限定类名(如:Person Bean的id为person)。
也可使用@Component("Roger")方式来指定Bean的id。
经过为<context:component-config>配置子元素<context:include-filter>或者<context:exclude-filter>来调整扫描行为。
<context:include-filter>的type和expression属性一块儿来定义组件扫描策略。
过滤器类型 | 描述 |
annotation |
过滤器扫描使用指定注解所标注的那些类,经过expression属性指定要扫描的注解 |
assignable | 过滤器扫描派生于expression属性所指定类型的那些类 |
aspectj | 过滤器扫描与expression属性所指定的AspectJ表达式所匹配的那些类 |
custom | 使用自定义的org.springframework.core.type.TypeFilter实现类,该类由expression属性指定 |
regex | 过滤器扫描类的名称与expression属性所指定的正则表达式所匹配的那些类 |
例如:
<context:component-scan base-package="com.roger.spring.beans"> <context:include-filter type="assignable" expression="com.roger.spring.Address" /> </context:component-scan>
用极少许的xml来启用java配置:
<?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"> <context:component-scan base-package="com.roger.spring.beans"> </context:component-scan> </beans>
<context:component-scan>自动注册那些使用某种构造型(stereotype)注解所标注的Bean。
同时,也会自动加载使用@Configuration注解所标注的类。
在基于java的配置里使用@Configuration注解的java类,等价于xml配置中的<beans>元素。
@Configuration注解做为一个标识告知Spring:这个类将包含一个或多个Spring Bean的定义。
这些Bean的定义是使用@Bean注解所标注的方法。
例如:
有一个Person基类,Teacher类继承Person类,如下,声明一个简单的id为roger的Teacher Bean。
import org.springframework.context.annotation.Configuration; @Configuration public class SpringConfig { //Bean declaration methods go here //声明一个简单的Bean @Bean public Person roger() { return new Teacher(); } }
@Bean告知Spring这个方法将返回一个对象,该对象应该被注册为Spring应用上下文中的一个Bean,方法名做为Bean的id。
例如:
注入一个引用
import org.springframework.context.annotation.Configuration; @Configuration public class SpringConfig { //Bean declaration methods go here @Bean public Address address() { return new Address(); } @Bean public Person roger() { return new Teacher(address()); } }
注意:在Spring的java配置中,经过声明方法引用一个Bean并不等同于调用该方法。经过@Bean注解标注address()方法,要在其余Bean的声明方法中引用这个方法时,Spring都会拦截方法的调用,并尝试在应用上下文中查找该Bean,而不是让方法建立一个新的实例。