首页 > 代码库 > 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)注解所注解的类,包括:
- @Component
- @Controller
- @Repository
- @Service
- 使用@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 自动装配