首页 > 代码库 > Spring 自动装配

Spring 自动装配

严格的说,实际分为自动检测和自动装配两方面。

先说自动检测,自动检测就是允许Spring自动检测与定义Bean。这就意味着,不使用<bean/>,你也能实现Spring中大多数的Bean的定义和装配。

为启用这一功能,你得引入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">
        
    <context:component-scan
        base-package="org.chen.auto">
    </context:component-scan>
</beans>

并使用context:component-scan,并在base-package指出在哪些包下的类能被检测。

问题来了,如果你要使多个包下的类都能被检测怎么办?谷歌 “context:component-scan multiple package”,答案是:

<context:component-scan base-package="x.y.z.service, x.y.z.controller" />

就是用都逗号分隔。


那么Spring会为哪些类注册成Bean呢?默认的,<context:component-scan>会查找使用构造型(stereotype)注解所注解的类,包括:

  1. @Component
  2. @Controller
  3. @Repository
  4. @Service
  5. 使用@Component标注的自定义注解


package org.chen.auto;

import org.springframework.stereotype.Component;

@Component("my-guitar")
public class Guitar implements Instrument {

	public void play() {
		System.out.println("play guitar ... ");
	}

}

上面的Guitar类,使用了@Component注解,默认其ID是无限定类名,即guitar,当然你可以在使用注解时自定义。

这样就完成了自动检测和注册。


但是,如果需要把一个包下面的所有类写上个@Component也是够烦的。Spring为我们提供了过滤组件的扫描。

<context:include-filter /> 和 <context:exclude-filter />,分别是包含和排除。

比如,

如果我们使用,

  <context:component-scan
        base-package="org.chen.auto">
        <context:include-filter type="assignable" expression="org.chen.auto.Instrument"/>
    </context:component-scan>

表明所有实现Instrument的类会被检测并注册(相当于自己加上了@Component)。

type是过滤类型,


基于注解的过滤方式是最常用的。


下面说说自动装配。

@Autowired注解和@Inject能完成类似的工作。不同的是,@Inject是Java语言自带的,推荐用它,javax.inject是JavaEE版本的,如果你使用的是Java SE版本,需要手动添加到build path,如果你使用的是Maven,可添加下面的依赖:

	<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
       </dependency>

@Inject可以用来自动装配熟悉、方法和构造器。

由于@Inject是按类型装配的,所以如果容器里有多个类型满足,则会报错。我们这时可以使用@Named来限定(默认使用Bean的ID)。


@Component
public class TestBean {

	@Inject
	@Named("pianeo")
	private Instrument instrument;
	
	public void say(){
		System.out.println("test bean is saying ...");
		
		instrument.play();
		
	}
}

文章的最后,给出自定义注解的方法,
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {}

如果要写出@Component,即

@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface MyAnnotation {}

其中,@Target是目标,表示该注解能用在何处。包括:

  • ElementType.TYPE (class, interface, enum)
  • ElementType.FIELD (instance variable)
  • ElementType.METHOD
  • ElementType.PARAMETER
  • ElementType.CONSTRUCTOR
  • ElementType.LOCAL_VARIABLE
  • ElementType.ANNOTATION_TYPE (on another annotation)
  • ElementType.PACKAGE (remember package-info.java)
含义都是英文翻译,这里不一一说明。


@Retention表示你将保持这个注解多久,


这是来自Oracle的文档的截图。有源码,.Class文件,运行时三种。

Spring 自动装配