什么是Bean
Bean是由Spring Ioc容器管理的Java对象,可以被Spring框架的其他部分引用(依赖注入)。
Bean的定义方法
Spring可以通过org.springframework.context.annotation中的四个注解对Bean进行定义,这四个注解主要区别在于定义框架中不同层的Bean:
注释 | 修饰对象 | 定义Bean的不同 |
@Bean | 方法,本质是修饰方法的返回值 | / |
@Service | 类 | 定义服务层的Bean |
@Controller | 类 | 定义控制层的Bean,除了注释Bean以外还为类提供控制器的相关方法 |
@Repository | 类 | 定义数据访问层的Bean,除了注释Bean以外,还为类提供处理数据访问相关异常的处理方法 |
@Component | 类 | 定义未明确层次的Bean |
Bean基于注释的自动注入
Bean基于注释的自动注入主要通过@Autowired、@Resource、@Inject三种方法,其中@Autowired是Spring的注解(来源于org.springframework.beans.factory.annotation包),@Resource和@Inject是Java自己的注解(来源于javax包),在这两个java自己的注解中,@Resource是基于JSR-250的注解,@Inject是基于JSR-330的注解,两个注解实现的功能相似。Spring框架目前也完全支持基于Java的两个注解(也能够对做注解的类或方法进行扫描,并纳入IoC容器管理)。下面重点从匹配的优先顺序等方面说明三个注释的区别。
注解 | 默认匹配顺序 | Package | 注入对象 |
@Autowired | By Type -> By Qualifier -> By Name | Spring | Field、setter、Constructor |
@Resource | By Name -> By Type -> By Qualifier | Javax | Field、setter、Constructor |
@Inject | By Type -> By Qualifier -> By Name | Javax | Field、setter、Constructor |
其中三个注解的By Type、By Name和By Qualifier的形式不同:
注解 | By Type | By Name | By Qualifier |
@Autowired | @Autowired | @Autowired* | @Autowired @Qualifier("namedFile") |
@Resource | @Resource | @Resource(name="namedFile")(name属性如果不设置,默认是类名) | @Resource @Qualifier("namedFile") |
@Inject | @Inject | @Inject @Named("namedFile")(name属性如果不设置,默认是类名) | @Inject @Qualifier("namedFile") |
*注意@Autowired的By Name要保证bean的name与@Autowired所注释的类(或者setter)的name一样,如:
public interface ArbitraryDependency{
public String toString();
}
@Component(value="autowiredFieldDependency_1")
public class ArbitraryDependency_1 implement ArbitraryDependency{
private final String label = "Arbitrary_Dependency_1";
@Override
public String toString() {
return label;
}
}
///
@Component(value="autowiredFieldDependency_2")
public class ArbitraryDependency_2 implement ArbitraryDependency{
private final String label = "Arbitrary_Dependency_2";
@Override
public String toString() {
return label;
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestAutowiredName.class)
public class FieldAutowiredNameIntegrationTest {
@Autowired
private ArbitraryDependency autowiredFieldDependency_1;
@Test
public void givenAutowired_WhenSetOnField_ThenDependencyResolved(){
assertNotNull(autowiredFieldDependency);
assertEquals("Arbitrary Dependency",
autowiredFieldDependency.toString());
}
}
这个例子中,定义了两个与autowiredFieldDependency_1类型相同的Bean,因此@Autowired默认的By Type失效,通过By Name原则进行匹配,其中autowiredFieldDependency_1的name(@Autowire修饰类的name默认是类名)与@Component的value属性一致,因此匹配成功。