Bean管理的注解实现及例子
注:从Spring3.0开始,Spring JavaConfig项目提供了很多特性,包括使用java的时候不用XML定义bean,比如@Configuration,@Bean,@Import,@DependsOn
- Classpath扫描与组件管理
- @Component,@Reposiory,@Service,@Controller
- @Component是一个通用注解,可用于任何bean
- @Repository通常用于注解DAO类,即持久层
- @Service通常用于注解Service类,即服务层
- @Controller通常用于Controller类,即控制层(MVC)
类的自动检测与注册Bean
- Spring可以自动检测类并注册Bean到ApplicationContext中
@Service public class SimpleMovieLister{ @Autowired public SimpleMovieLister(MovieFinder movieFinder) { this.movieFinder = movieFinder; }
- 为了能够检测这些类并注册相应的Bean,需要下面内容
<beans ..........>
<context:component-scan base-package="org.example">
</beans>
- < context:component-scan>包含< context-annotation-config>,通常在使用前者后,不用再使用后者
- AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor也会被包含进来
使用过滤器进行自定义扫描
- 默认情况下,类被自动发现并注册bean的条件是:使用@Component,@Repository,@Service,@Contraoller注解或者使用@Component的自定义注解
可以通过过滤器修改上面的行为,如:下面例子忽略所有的@Repository注解并用“Stub”代替
<beans> <context:component-scan base-package="org.example"> <context:include-filter type="regex" expression=".*Stub.*Repository"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/> </context:component-scan> </beans>
- 还可使用use-default-filters=”false”
定义Bean
扫描过程中组件被自动检测,那么Bean名称是由BeanNameGenerator生成的(@Component,@Repository,@Service,@Controller都会有个name属性用于显式设置Bean Name)
@Service("myMovieLister") public class SimpleMovieLister{ //... } @Repository public class MovieFinderImpl implements MovieFinder{ //... }
可定义bean命名策略,实现BeanNameGenerator接口,并一定要包含一个无参数构造函数
<beans> <context:component-scan base-package="org.example" name-generator="org.example.MyNameGenerator"/> </beans>
作用域(Scope)
通常情况下自动查找的Spring组件,其scope是singleton,Spring2。5提供了一个标识scope的注解是@Scope
@Scope("prototype") @Repository public class MovieFinderImpl implements MovieFinder { //... }
也可以自定义scope策略,实现ScopeMetadataResolver接口并提供一个无参构造器
<beans> <context:component-scan base-package="org.example" scope-resolver="org.example.MyScopeResover"> </beans>
代理方式
可以使用scoped-proxy属性指定代理,有三个值可选:no,interfaces,targetClass
<beans> <context:component-scan base-package="org.example" scoped-proxy="interfaces"/> </beans>
- A
< context:annotation-config/>
- 通过在基于XML的Spring配置如下标签(请注意包含上下文命名空间)
- 仅会查找在同一个applicationcontext中的bean注解
@Required
- @Required注解是用于bean属性的setter方法
这个注解仅仅表示,受影响的bean属性必须在配置时被填充,通过在bean定义或通过自动装配一个明确的属性值
public class SimpleMovieLister{ private MovieFinder movieFinder; @Required public void setMovieFinder(MovieFinder movieFinder){ this.movieFinder = movieFinder; } }
@Autowired
- 可以将Autowired注解为“传统”的setter方法
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder){
this.movieFInder = movieFinder;
}
可用于构造器或成员变量
@Autowired private MovieCatalog movieCatalog; private CustomerPerferenceDao customerPerferenceDao; @Autowired public MovieRecommender(CustomerPerferenceDao customerPreferenceDao) { this.customerPreferenceDao = customerPreferenceDao; }
默认情况下,如果因找不到合适的bean将会导致autowiring失败抛出异常,可以通过下面的方式避免
public class SimpleMovieLister{ private MovieFinder movieFinder; @Autowired(required = false) public void setMovieFInder(MovieFinder movieFinder) { this.movieFinder = movieFinder; } }
- 每个类只能有一个构造器被标记为required=true
- @Autowired的必要属性,建议使用@Required注解
可以使用@Autowired注解那些众所周知的解析依赖性接口,比如:BeanFactory,ApplicationContext,Environment,ResourceLoader,ApplicationEventPubliser,and MessageSource
public class MovieRecommender{ @Autowired private ApplicationContext context; public MovieRecommender(){ } }
可以通过添加注解给需要该类型的数组的字段或方法,以提供ApplicationContext中的所有特定类型的bean
private Set<MovieCatalog> movieCatalogs; @Autowired public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs){ this.movieCatalogs = movieCatalogs; }
可以用于装配key为String的Map
private Map<String, MovieCatalog> movieCatalogs; @AutoWired public void setMovieCatalogs(map<String, MovieCatalog> movieCatalogs) { this.movieCatalogs = movieCatalogs; }
- 如果希望数组有序,可以让bean实现org.springframework.core.Ordered接口或使用的@Order注解
- @Autowired是由Spring BeanPostProcessor处理的,所以不能在自己的BeanPostProcessor或BeanFactoryPostProcessor类型应用这些注解,这些类型必须通过XML或者Spring的@Bean注解加载
- 阿
- 阿
- 可以将Autowired注解为“传统”的setter方法
@Qualifier
按类型自动装配可能多个bean实例的情况,可以使用Spring的@Qualifier注解缩小范围(或指定唯一),也可以用于指定单独的构造器参数或方法参数
public class MovieRecommender{ @Autowired @Qualifier("main") private MovieCatalog movieCatalog; } public class MovieRecommender{ private MovieCatalog movieCatalog; private CustomerPreferenceDao customerPreferenceDao; @Autowired public void prepare(@Qualifier("main")MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao){ this.movieCatalog = movieCatalog; this.customerPreferenceDao = customerPreferenceDao; } }
- 可用于注解集合类型变量
- 如果通过名字进行注解注入,主要使用的不是@Autowired(即使在技术上能够通过@Qualifier指定bean的名字),替代方式时使用JSR-250@Resource注解,它是通过其独特的名称来定义来识别特定的目标(这是一个与所声明的类型是无关的匹配过程)
- 因语义差异,集合或Map类型的bean无法通过@Autowired来注入,因为没有类型匹配到这样的bean,为这些bean使用@Resource注解,通过唯一名称引用集合或Map的bean
- @Autowired适用于fields,constructors,multi-argument method这些允许在参数级别使用@Qualifier注解缩小范围的情况
- @Resource是用于成员变量、只有一个参数的setter方法,所以在目标是构造器或一个多参数方法时,最好的方式是使用qualifiers
定义自己的qualifier注解并使用
@Target((ElementType.FIELD.FIELD,ElementType.PARAMETER)) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface Genre{ String value(); } public class MovieRecommender{ @Autowired @Genre("Action") private MovieCatalog actionCatalog; private MovieCatalog comedyCatalog; @Autowired public void setComedyCatalog(@Genre("Comedy") MovieCatalog comedyCatalog) { this.comedyCatalog = comedyCatalog; } }
- 自定义
- 阿
- @Resource