基于注解的容器配置
注释比用于配置Spring的XML更好吗?
引入基于注释的配置引发了这种方法是否比XML更好的问题。简短的答案取决于你自己的需要。比较优秀的答案是每种方法都有其优缺点,通常由开发人员决定哪种策略更适合他们。
由于它们被定义的方式不同,注释在其声明中提供了大量的上下文,从而导致更短,更简洁的配置。
但是,XML在接触组件时不需要触及其源代码或重新编译它们就能胜任。一些开发人员更喜欢布线接近源,而另一些开发人员则认为注释类不再是POJO,而且配置变得分散,难以控制。
无论选择什么,Spring都可以适应两种风格,甚至可以将它们混合在一起。值得指出的是,通过JavaConfig
选项,Spring允许以非侵入方式使用注释,而无需触及目标组件源代码,并且在工具方面,Spring Tool Suite支持所有配置样式 。
一、基于注释
基于注释的配置提供了XML设置的替代方法,该配置依赖字节码元数据来连接组件而不是角括号声明。开发人员不是使用XML来描述bean布线,而是通过在相关的类,方法或字段声明中使用注释将配置移入组件类本身。
正如所提到RequiredAnnotationBeanPostProcessor
示例,使用BeanPostProcessor结合注解是扩展Spring IoC容器的常用手段。
例如,Spring 2.0引入了使用@Required
注解强制执行所需属性的可能性。Spring 2.5使得遵循相同的通用方法来驱动Spring的依赖注入成为可能。
本质上来说,@Autowired
注释提供了与Autowiring
协作者中描述的功能相同的功能,但具有更细致的控制和更广泛的适用性。
注释注入是在 XML注入之前执行的,因此后者配置将覆盖通过两种方法连接的属性的前者。
与往常一样,您可以将它们注册为单独的bean定义,但也可以通过在基于XML的Spring配置中包含以下标记来隐式注册它们(注意包含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:annotation-config/>
</beans>
(该隐式注册的后处理器包括 AutowiredAnnotationBeanPostProcessor
, CommonAnnotationBeanPostProcessor
, PersistenceAnnotationBeanPostProcessor
,
以及前述 RequiredAnnotationBeanPostProcessor
)。
<context:annotation-config/>
只在与其定义的应用程序上下文中查找bean上的注释。这意味着,如果你 <context:annotation-config/>
输入一个WebApplicationContextfor DispatcherServlet,它只会检查@Autowired
控制器中的bean,而不是你的服务。
二、@Required
该@Required注释适用于bean属性setter方法,如下面的例子:
public class SimpleMovieLister {
private MovieFinder movieFinder;
//如果你在使用SimpleMovieLister这个类,必须通过setMovieFinder
//的方式,将movieFinder填充到这个类中
@Required
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
这个注解简单地表明受影响的bean属性必须在配置时通过bean定义中的显式属性值或通过自动装配来填充。如果受影响的bean属性尚未填充,容器将引发异常; 这允许急切和明确的失败,避免NullPointerException稍后的s等。仍然建议您将断言放入bean类本身,例如,放入init方法中。这样做即使在容器外部使用该类时也会强制执行那些必需的引用和值。
三、@Autowired
在下面的例子中,JSR 330的@Inject注解可以用来代替Spring的@Autowired注解。
- 1.您可以将
@Autowired
注释应用于构造函数:
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
//构造函数(构造器)
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
从Spring Framework 4.3开始,@Autowired如果目标bean只定义了一个构造函数,那么对这样的构造函数的注释就不再需要了。但是,如果有几个构造函数可用,则必须至少注明一个构造函数来教授容器使用哪一个。
- 2.正如预期的那样,您还可以将@Autowired注释应用于“传统”setter方法:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
- 3.您还可以将注释应用于具有任意名称和/或多个参数的方法:
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
- 4.您也可以应用于@Autowired字段,甚至可以将其与构造函数混合使用:
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
private MovieCatalog movieCatalog;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
确保你的目标组件(例如MovieCatalog,CustomerPreferenceDao)始终得到您正在使用您的类型声明@Autowired-annotated注入点。否则由于在运行时找不到类型匹配,注入可能会失败。
对于通过类路径扫描找到的XML定义的bean或组件类,容器通常会预先知道具体类型。但是,对于@Bean工厂方法,您需要确保声明的返回类型具有足够的表现力。对于实现多个接口的组件或可能由其实现类型引用的组件,请考虑在工厂方法中声明最具体的返回类型(至少按照注入点对bean引用的要求)。
- 5.也可以通过向需要该类型数组的字段或方法添加注释来提供特定类型的所有 bean
ApplicationContext
:
public class MovieRecommender {
//例如在这里需要movieCatalogs,它的类型是一个MovieCatalog数组
@Autowired
private MovieCatalog[] movieCatalogs;
// ...
}
- 6.类型化的集合也是如此:
public class MovieRecommender {
private Set<MovieCatalog> movieCatalogs;
//需要用到set集合类型的MovieCatalog
@Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}
如果您希望数组或列表中的项目按特定顺序排序,您的目标
bean
可以实现org.springframework.core.Ordered
接口或使用@Order
或使用标准@Priority
注释。否则,他们的顺序将遵循容器中相应目标bean
定义的注册顺序。
所述@Order
注释可以在目标类上面,而且也对被声明@Bean(在的多个定义的情况下用相同的bean类)的方法,有可能为每bean定义非常个体。@Order值可能会影响注入点的优先级,但请注意,它们不影响单例Bean启动顺序,这是由依赖关系和@DependsOn声明确定的正交关系。
请注意,由于标准javax.annotation.Priority
注释无法@Bean在方法中声明,因此在该级别上不可用。它的语义可以通过@Order结合@Primary每种类型的单个bean的值来建模。
- 7.甚至类型是Map类型的也是可以注入成功的,只要希望的预期的类型的Key是
String
类型的。这个Map的值可以包括所有期望的类型,并且这哥Map的Key可以包括相应的Bean的名字。
public class MovieRecommender {
private Map<String, MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}
- 8.默认情况下,每当获取不到需要注入的Bean的时候,这个注入就会失败。默认行为是将注释的方法,构造函数和字段视为指示所需的依赖项。
但是这种情况是可以改变的:
public class SimpleMovieLister {
private MovieFinder movieFinder;
//表示非必需
@Autowired(required = false)
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
每个类只能有一个带注释的构造函数可以标记为必需,但可以注释多个不必需的构造函数。在这种情况下,每个人都被认为是候选人,而Spring使用可以满足其依赖性的最符合的构造函数,即具有最多参数的构造函数。
建议在@Autowired
注释中使用Required
必需的属性。将所需的属性表示该属性是否需要自动装配的目的,如果它不是必需的,自动装配的属性被忽略。另一方面则更强大,因为它强制执行由集装箱支持的任何手段设定的财产。如果没有值被注入,则会引发相应的异常。
- 9.或者,您可以通过Java 8来表达特定依赖项的非必需性质java.util.Optional:
Optional
表示可选
public class SimpleMovieLister {
@Autowired
public void setMovieFinder(Optional<MovieFinder> movieFinder) {
...
}
}
- 10.从Spring Framework 5.0开始,您也可以使用
@Nullable
注释(任何包中的任何类型的注释,例如javax.annotation.NullableJSR-305
):@Nullable
表示可选
public class SimpleMovieLister {
@Autowired
public void setMovieFinder(@Nullable MovieFinder movieFinder) {
...
}
}
- 11.您还可以使用
@Autowired
对于那些众所周知的解析依赖接口:BeanFactory
,ApplicationContext
,Environment
,ResourceLoader
,ApplicationEventPublisher
,和MessageSource
。这些接口及其扩展接口(如ConfigurableApplicationContext
或`ResourcePatternResolver
)会自动解析,而无需进行特殊设置。
public class MovieRecommender {
@Autowired
private ApplicationContext context;
public MovieRecommender() {
}
// ...
}
三、使用@Primary微调基于注释的自动装配
由于按类型自动装配可能会导致多个候选人,因此通常需要对选择过程有更多的控制权。一种方法是通过Spring的@Primary注解来实现这一点 。@Primary表示当多个bean可以自动装配到单值依赖项时,应该给予一个特定的bean优先。如果在候选人中确实存在一个“主要”bean,它将是自动装配的值。
假设我们有以下定义firstMovieCatalog为 主要的 配置MovieCatalog。
@Configuration
public class MovieConfiguration {
@Bean
@Primary
public MovieCatalog firstMovieCatalog() { ... }
@Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
有了这样的配置,以下MovieRecommender将自动装配 firstMovieCatalog。
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
// ...
}
相应的bean定义如下所示。
<?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/>
<bean class="example.SimpleMovieCatalog" primary="true">
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
四、使用限定符对基于注释的自动装配进行微调
1.@Primary
是可以确定一个主要候选人时使用多个实例的自动装配的有效方法。当需要对选择过程进行更多控制时,@Qualifier可以使用Spring的注释。您可以将限定符值与特定参数相关联,缩小匹配类型的集合,以便为每个参数选择特定的bean。在最简单的情况下,这可以是一个简单的描述性值:
public class MovieRecommender {
@Autowired
@Qualifier("main")
private MovieCatalog movieCatalog;
// ...
}
@Qualifier注释也可以在单独的构造器参数或方法参数指定:
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;
}
// ...
}
相应的bean定义如下所示。具有限定符值“main”的bean与用相同值限定的构造函数参数连线。
<?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/>
<bean class="example.SimpleMovieCatalog">
<qualifier value="main"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier value="action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<!-- 下面这个和上面的qualifier value="main"的bean相关联 -->
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
2.限定符的适用范围
对于回退匹配,bean名称被视为默认限定符值。因此,您可以使用id“main”而不是嵌套的限定符元素来定义bean,从而得到相同的匹配结果。
但是,尽管您可以使用此约定来通过名称引用特定的bean,但@Autowired基本上是使用可选的语义限定符进行类型驱动的注入。
这意味着限定符值(即使使用bean名称回调)也会在匹配类型集合内缩小语义;它们不会在语义上表达对唯一bean id的引用。
良好的限定符值是“main”或“EMEA”或“持久性”,表示与bean无关的特定组件的特征id,
例如,限定符也适用于键入的集合,如上所述Set<MovieCatalog>
。在这种情况下,根据声明的限定符的所有匹配的Bean将作为集合注入。这意味着限定词不必是唯一的; 它们只是构成过滤标准。例如,您可以定义多个MovieCatalog具有相同限定符值“action”的bean,所有这些bean都将被注入到Set<MovieCatalog>
注释中@Qualifier("action")
。
在类型匹配的候选项中针对目标bean名称选择限定符值并不需要@Qualifier注入点处的注释。如果没有其他解析指示符(例如限定符或主标记),那么对于非唯一的依赖性情况,Spring将匹配注入点名称(即字段名称或参数名称)与目标bean名称,并选择相同的名称,命名候选人,如果有的话。
也就是说,如果您打算按名称表示注解驱动的注入@Autowired,即使可以在类型匹配的候选中使用bean名称进行选择,也不要主要使用。
相反,使用JSR-250 @Resource注释,该注释在语义上定义为通过其唯一名称来标识特定目标组件,并且声明的类型与匹配过程无关。
@Autowired具有相当不同的语义:在按类型选择候选bean之后,指定的字符串限定符值将仅在这些类型选择的候选者中被考虑,例如,将“帐户”限定符与用相同限定符标签标记的bean相匹配。
对于本身被定义为集合/映射或数组类型的bean,这@Resource 是一个很好的解决方案,通过唯一名称引用特定集合或数组bean。
也就是说,@Autowired只要元素类型信息保留在@Bean返回类型签名或集合继承层次结构中,就可以通过Spring的类型匹配算法来匹配集合/映射和数组类型 。在这种情况下,可以使用限定符值在相同类型的集合中进行选择,如前一段所述。
从4.3开始,@Autowired也考虑自引用注入,即引用回当前注入的bean。请注意,自我注入是后备; 对其他组件的正常依赖关系始终具有优先权。
从这个意义上说,自我引用不参与正规的候选人选择,因此尤其不是主要的; 相反,它们总是以最低优先权结束。
实际上,只能使用自引用作为最后的手段,例如通过bean的事务代理来调用同一实例上的其他方法:考虑在这种情况下将受影响的方法分解为单独的委托bean。或者,使用@Resource它可以通过其唯一名称获取当前bean的代理。
@Autowired适用于字段,构造函数和多参数方法,允许通过参数级别的限定符注释进行缩小。相比之下,@Resource 仅支持具有单个参数的字段和bean属性设置方法。因此,如果注入目标是构造函数或多参数方法,则坚持使用限定符。
您可以创建自己的自定义限定符注释。只需定义一个注释并@Qualifier在您的定义中提供注释:
@Target({ElementType.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;
}
// ...
}
接下来,提供候选bean定义的信息。您可以添加 <qualifier/>
标签作为标签的子元素,<bean/>
然后指定type
和 value
匹配您的自定义限定符注释。该类型与注释的完全限定类名相匹配。或者,如果没有相互冲突名称存在的风险,为了方便起见,您可以使用短名称。以下示例演示了这两种方法。
<?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/>
<bean class="example.SimpleMovieCatalog">
<qualifier type="Genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier type="example.Genre" value="Comedy"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
在Classpath扫描和托管组件中,您将看到一种基于注释的替代方法来提供XML中的限定符元数据。
在某些情况下,使用没有值的注释可能就足够了。当注释提供更通用的用途并且可以应用于多种不同类型的依赖关系时,这可能很有用。例如,您可以提供一个脱机 目录,当没有可用的Internet连接时将搜索该目录。首先定义简单的注释:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Offline {
}
然后将注释添加到要自动装配的字段或属性中:
public class MovieRecommender {
@Autowired
@Offline
private MovieCatalog offlineCatalog;
// ...
}
现在,bean定义只需要一个限定符type:
<bean class="example.SimpleMovieCatalog">
<qualifier type="Offline"/>
<!-- inject any dependencies required by this bean -->
</bean>
您还可以定义接受指定属性的自定义限定符注释,而不是简单value属性。如果在一个字段或参数上指定多个属性值进行自动装配,则一个bean定义必须匹配 所有这些属性值才能被视为自动装配候选者。作为示例,请考虑以下注释定义:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MovieQualifier {
String genre();
Format format();
}
在这种情况下Format是枚举:
public enum Format {
VHS, DVD, BLURAY
}
要自动装配的字段使用自定义限定符进行注释,并包含两个属性的值:genre和format。
public class MovieRecommender {
@Autowired
@MovieQualifier(format=Format.VHS, genre="Action")
private MovieCatalog actionVhsCatalog;
@Autowired
@MovieQualifier(format=Format.VHS, genre="Comedy")
private MovieCatalog comedyVhsCatalog;
@Autowired
@MovieQualifier(format=Format.DVD, genre="Action")
private MovieCatalog actionDvdCatalog;
@Autowired
@MovieQualifier(format=Format.BLURAY, genre="Comedy")
private MovieCatalog comedyBluRayCatalog;
// ...
}
最后,bean定义应该包含匹配的限定符值。这个例子还表明可以使用bean
元属性来代替 <qualifier/>
子元素。如果可用,则<qualifier/>
其及其属性优先,但<meta/>
如果不存在此类限定符,则自动装配机制会回退标签中提供的值 ,如以下示例中的最后两个bean定义所示。
<?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/>
<bean class="example.SimpleMovieCatalog">
<qualifier type="MovieQualifier">
<attribute key="format" value="VHS"/>
<attribute key="genre" value="Action"/>
</qualifier>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier type="MovieQualifier">
<attribute key="format" value="VHS"/>
<attribute key="genre" value="Comedy"/>
</qualifier>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<meta key="format" value="DVD"/>
<meta key="genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<meta key="format" value="BLURAY"/>
<meta key="genre" value="Comedy"/>
<!-- inject any dependencies required by this bean -->
</bean>
</beans>
五、使用泛型作为自动装配限定符
除了@Qualifier注释之外,还可以使用Java通用类型作为隐式形式的限定条件。例如,假设您有以下配置:
@Configuration
public class MyConfiguration {
@Bean
public StringStore stringStore() {
return new StringStore();
}
@Bean
public IntegerStore integerStore() {
return new IntegerStore();
}
}
假设上述bean实现一个通用接口,即Store<String>
和 Store<Integer>
,你可以@Autowire
在Store
界面和通用将作为一个限定:
@Autowired
private Store<String> s1; // <String> qualifier, injects the stringStore bean
@Autowired
private Store<Integer> s2; // <Integer> qualifier, injects the integerStore bean
自动装配列表,地图和阵列时也适用通用限定符:
// Inject all Store beans as long as they have an <Integer> generic
// Store<String> beans will not appear in this list
@Autowired
private List<Store<Integer>> s;
六、CustomAutowireConfigurer
这 CustomAutowireConfigurer
是一个BeanFactoryPostProcessor
让您可以注册自己的自定义限定符注释类型,即使它们没有用Spring的@Qualifier注释注释。
<bean id="customAutowireConfigurer"
class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>example.CustomQualifier</value>
</set>
</property>
</bean>
通过以下方式AutowireCandidateResolver确定autowire候选人:
- autowire-candidate每个bean定义的值
- 元素上default-autowire-candidates可用的任何模式
<beans/>
- @Qualifier注释的存在以及注册的任何自定义注释CustomAutowireConfigurer
当多个bean被认定为自动装配候选者时,“primary”的确定如下:如果候选者中恰好有一个bean定义primary 属性设置为true,则它将被选中。
七、@Resource
Spring还支持使用@Resource字段上的JSR-250 批注或bean属性设置器方法进行注入。这是Java EE 5和6中的常见模式,例如在JSF 1.2托管bean或JAX-WS 2.0端点中。Spring也支持Spring管理对象的这种模式。
@Resource需要一个名称属性,默认情况下,Spring将该值解释为要注入的bean名称。换句话说,它遵循名义语义,如本例所示:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Resource(name="myMovieFinder")
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
如果没有明确指定名称,则默认名称是从字段名称或setter方法派生的。如果是字段,则需要字段名称; 在setter方法的情况下,它采用bean属性名称。所以下面的例子将把名为“movieFinder”的bean注入到它的setter方法中:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Resource
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
提供注解的名称解析由一个bean的名称 ApplicationContext,其中的CommonAnnotationBeanPostProcessor知道。如果SimpleJndiBeanFactory 明确配置Spring的名字,可以通过JNDI解析名称 。但是,建议您依赖默认行为并简单地使用Spring的JNDI查找功能来保留间接级别。
在专属情况下,@Resource不指定明确的名称,以及类似的使用@Autowired,@Resource发现的主要类型的比赛,而不是一个具体的bean并解决众所周知的解析依存关系:BeanFactory, ApplicationContext,ResourceLoader,ApplicationEventPublisher,和MessageSource 接口。
因此,在以下示例中,该customerPreferenceDao字段首先查找名为customerPreferenceDao的bean,然后返回到该类型的主类型匹配 CustomerPreferenceDao。“上下文”字段是基于已知的可解析依赖类型注入的ApplicationContext。
public class MovieRecommender {
@Resource
private CustomerPreferenceDao customerPreferenceDao;
@Resource
private ApplicationContext context;
public MovieRecommender() {
}
// ...
}
八、@PostConstruct和@PreDestroy
这个CommonAnnotationBeanPostProcessor
不仅承认了@Resource
注解也是JSR-250 的生命周期注解。在Spring 2.5中引入的对这些注释的支持为初始化回调函数
和销毁回调函数
提供了另一种替代方案 。假设 CommonAnnotationBeanPostProcessorSpring
在Spring中注册 ApplicationContext,则在生命周期的相同时间点调用携带这些注释中的一个的方法,如相应的Spring生命周期接口方法或显式声明的回调方法。在下面的示例中,缓存将在初始化时预填充,并在销毁时清除。
ublic class CachingMovieLister {
@PostConstruct
public void populateMovieCache() {
// populates the movie cache upon initialization...
}
@PreDestroy
public void clearMovieCache() {
// clears the movie cache upon destruction...
}
}
有关组合各种生命周期机制的效果的详细信息,请参阅 组合生命周期机制。
好啦,关于IOC中的基于注解的容器配置就到这里啦!