20191226 Spring官方文档(Core 1.9)
1.9。基于注释的容器配置
由于定义方式的不同,注释在声明中提供了很多上下文,从而使配置更短,更简洁。但是,XML擅长装配组件而不接触其源代码或重新编译它们。一些开发人员更喜欢将装配靠近源代码,而另一些开发人员则认为带注释的类不再是POJO,而且,配置变得分散并且难以控制。无论选择如何,Spring都可以容纳两种样式,甚至可以将它们混合在一起。
基于注释的配置提供了XML设置的替代方法,该配置依赖字节码元数据来装配组件,而不是尖括号声明。通过使用相关类,方法或字段声明上的注释,开发人员无需使用XML来描述bean的装配,而是将配置移入组件类本身。如示例中所述:RequiredAnnotationBeanPostProcessor
,将BeanPostProcessor
和注释一起使用是扩展Spring IoC容器的常用方法。例如,Spring 2.0引入了使用@Required
注释强制执行必需属性的可能性。Spring 2.5使遵循相同的通用方法来驱动Spring的依赖注入成为可能。本质上,@Autowired
注释提供了与自动装配协作器中所述的功能相同的功能。但具有更细粒度的控制和更广泛的适用性。Spring 2.5还添加了对JSR-250注解(例如 @PostConstruct
和@PreDestroy
)的支持。Spring 3.0增加了对javax.inject
包中包含的JSR-330(Java依赖注入)注释的支持,例如@Inject
和@Named
。
注释注入在XML注入之前执行。因此,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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
隐式注册后处理器包括 AutowiredAnnotationBeanPostProcessor
, CommonAnnotationBeanPostProcessor
, PersistenceAnnotationBeanPostProcessor
,和前面提到的 RequiredAnnotationBeanPostProcessor
。
<context:annotation-config/>
只在定义它的相同应用程序上下文中查找关于bean的注释。这意味着,如果在包含DispatcherServlet
的WebApplicationContextfor
中放入<context:annotation-config/>
,则仅检查控制器中的@Autowired
bean,而不检查服务中的bean。
1.9.1。@Required
@Required
注释适用于bean属性setter方法
此注释指示必须在配置时通过bean定义中的显式属性值或通过自动装配来填充受影响的bean属性。如果尚未填充受影响的bean属性,则容器将引发异常。这允许急切和显式的失败,避免之后的NullPointerException
。我们仍然建议您将断言放入bean类本身中(例如,放入init方法中)。这样做会强制执行那些必需的引用和值,即使您在容器外部使用该类也是如此。
从Spring Framework 5.1开始,正式弃用了@Required
,以支持对所需的设置(或Bean属性设置器方法的InitializingBean.afterPropertiesSet()
自定义实现)使用构造函数注入 。
1.9.2。使用@Autowired
可以将@Autowired
注释应用于构造函数。
从Spring Framework 4.3开始,如果目标bean只定义一个构造函数,则不再需要在该构造函数上添加@Autowired注释。但是,如果有几个构造函数可用,则必须至少注释一个构造函数,以指示容器使用哪个构造函数。
可以将@Autowired注释应用于传统的 setter方法。
可以将注释应用于具有任意名称和多个参数的方法
可以将@Autowired应用于字段,甚至可以将其与构造函数混合使用
对于通过类路径扫描找到的XML定义的bean或组件类,容器通常预先知道具体的类型。但是,对于@Bean
工厂方法,您需要确保声明的返回类型具有足够的表现力。对于实现多个接口的组件或可能由其实现类型引用的组件,请考虑在工厂方法中声明最具体的返回类型(至少根据引用您的bean的注入点的要求具体声明)。
还可以通过将@Autowired注解添加到需要该类型数组的字段或方法中,指示Spring从ApplicationContext提供特定类型的所有bean。
@Autowired
private MovieCatalog[] movieCatalogs;
这同样适用于类型化集合
private Set<MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
如果您希望数组或列表中的项目以特定顺序排序,则目标bean可以实现org.springframework.core.Ordered
接口或使用@Order
或标准@Priority
注释。否则,它们的顺序将遵循容器中相应目标bean定义的注册顺序。
您可以在目标类级别和@Bean
方法上声明@Order
注释,可能是针对单个bean定义(在使用同一bean类的多个定义的情况下)。@Order值可能会影响注入点的优先级,但请注意它们不会影响单例启动顺序,这是由依赖关系和@DependsOn
声明确定的正交关系。
请注意,标准javax.annotation.Priority
注释在@Bean
级别不可用 ,因为无法在方法上声明它。可以通过将@Order
值与每个类型的单个@Primary
bean 结合使用来对其语义进行建模。
甚至预期的键类型为Map,只要键类型为String,也可以自动装配。映射值包含所有预期类型的bean,并且键包含相应的bean名称。
private Map<String, MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
默认情况下,当给定注入点没有匹配的候选bean可用时,自动装配将失败。对于声明的数组,集合或映射,至少应有一个匹配元素。
默认行为是将带注释的方法和字段视为所需的依赖项。您可以更改此行为,使框架可以通过将其标记为不需要来跳过不满意的注入点(即将@Autowired
的required
属性设置为false
)
private MovieFinder movieFinder;
@Autowired(required = false)
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
如果非required的方法的依赖项不可用(或在多个参数的情况下,其中一个依赖项不可用),则根本不会调用该方法。在这种情况下,完全不需要填充非必需字段,而将其默认值保留在适当的位置。
注入的构造函数和工厂方法参数是一种特殊情况,因为由于Spring的构造函数解析算法可能会处理多个构造函数,所以@Autowired
中的required
属性含义有所不同。默认情况下,构造函数和工厂方法参数是必需的,但是在单构造函数场景中有一些特殊规则,例如,如果没有可用的匹配bean,则多元素注入点(数组,集合,映射)解析为空实例。这允许一种通用的实现模式,其中所有依赖项都可以在唯一的多参数构造函数中声明,例如,声明为不带@Autowired注释的单个公共构造函数。
任何给定bean类都只能在一个构造函数上声明required
属性为true的@Autowired
,这表示在用作Spring bean时可以自动装配的构造函数。 此外,如果required属性设置为true,则只能使用@Autowired注释单个构造函数。 如果多个非required的构造函数声明了注释,则它们将被视为自动装配的候选对象。 将选择通过匹配Spring容器中的bean可以满足的依赖关系数量最多的构造函数。 如果没有一个满意的候选者,则将使用主/默认构造函数(如果存在)。 如果一个类仅声明一个单一的构造函数,即使没有注释,也将始终使用它。 带注释的构造函数不必是公共的。
建议在setter方法上使用@Autowired的required属性,而不建议使用弃用的@Required
注解。 将required属性设置为false表示该属性对于自动装配而言不是必需的,并且如果无法自动装配该属性,则将其忽略。 另一方面,@Required更为强大,因为它可以通过容器支持的任何方式强制设置属性,并且如果未定义任何值,则会引发相应的异常。
可以通过Java 8 java.util.Optional
来表达特定依赖项的非必需性质
@Autowired
public void setMovieFinder(Optional<MovieFinder> movieFinder) {
...
}
从Spring Framework 5.0开始,您还可以使用@Nullable注释(任何包中的任何类型,例如,javax.annotation.Nullable
来自JSR-305 的注释),或仅利用Kotlin内置的null安全支持:
@Autowired
public void setMovieFinder(@Nullable MovieFinder movieFinder) {
...
}
您还可以使用@Autowired
对于那些众所周知的解析依赖接口:BeanFactory
,ApplicationContext
,Environment
,ResourceLoader
, ApplicationEventPublisher
,和MessageSource
。这些接口及其扩展接口(例如ConfigurableApplicationContext
或ResourcePatternResolver
)将自动解析,而无需进行特殊设置。以下示例自动装配ApplicationContext对象:
@Autowired
private ApplicationContext context;
@Autowired
,@Inject
,@Value
,和@Resource
注释由Spring处理 BeanPostProcessor
实现。这意味着您不能在自己的BeanPostProcessor
或BeanFactoryPostProcessor
类型(如果有)中应用这些注释。必须使用XML或Spring @Bean方法显式装配这些类型。
1.9.3。通过@Primary微调基于注释的自动装配
由于按类型自动装配可能会导致多个候选对象,因此通常有必要更好地控制选择过程。一种实现此目的的方法是使用Spring的 @Primary
注释。@Primary指示当多个bean是要自动装配到单值依赖项的候选对象时,应给予特定bean优先权。如果候选对象中仅存在一个主bean,则它将成为自动装配的值。
@Configuration
public class MovieConfiguration {
@Bean
@Primary
public MovieCatalog firstMovieCatalog() { ... }
@Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
<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>
1.9.4。使用限定符对基于注释的自动装配进行微调
当可以确定一个主要候选者时,@Primary
是在存在多个同类型相同实例的情况下使用自动装配的有效方法。当您需要对选择过程进行更多控制时,可以使用Spring的@Qualifier
注释。您可以将限定符值与特定的参数相关联,从而缩小类型匹配的范围,以便为每个参数选择特定的bean。
@Autowired
@Qualifier("main")
private MovieCatalog movieCatalog;
可以在各个构造函数参数或方法参数上指定@Qualifier注释
@Autowired
public void prepare(@Qualifier("main") MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
相应的XML定义:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://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>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
对于后备匹配,bean名称被认为是默认的限定符值。因此,可以使用id为main而不是嵌套的qualifier
元素定义bean,从而得到相同的匹配结果。但是,尽管您可以使用此约定按名称引用特定的bean,但是@Autowired基本上是关于带有可选语义限定符的类型驱动的注入。这意味着,即使带有Bean名称后退的限定符值,在类型匹配集中也始终具有狭窄的语义。它们没有在语义上表示对唯一bean id的引用。良好的限定符值是 main 或 EMEA 或 persistent,表示特定组件的特征,这些特征独立于bean id,在使用匿名bean定义(例如前面的示例中的定义)的情况下,可以自动生成该特定组件。
限定符还适用于类型化的集合,如前面所述(例如,应用于Set@Qualifier("action")
的Set
在类型匹配的候选对象中,让限定符值针对目标bean名称进行选择,在注入点不需要@Qualifier注释。 如果没有其他解析度指示符(例如限定词或主标记),则对于非唯一依赖性情况,Spring将注入点名称(即字段名称或参数名称)与目标Bean名称进行匹配,然后选择 同名候选人(如果有)。
也就是说,如果您打算按名称表示注释驱动的注入,则即使它能够在类型匹配的候选对象中按bean名称进行选择,也不要主要使用@Autowired
。 而是使用JSR-250 @Resource
注解,该注解的语义定义是通过其唯一名称标识特定的目标组件,而声明的类型与匹配过程无关。 @Autowired具有不同的语义:在按类型选择候选bean之后,仅在那些类型选择的候选中考虑指定的String限定符值(例如,将account限定符与标记有相同限定符标签的bean进行匹配)。
对于本身定义为Collection,Map或array类型的bean,@Resource
是一个很好的解决方案,可以通过唯一名称引用特定的collection或array bean。也就是说,从4.3版本开始,只要元素类型信息保留在@Bean返回类型签名或集合继承层次结构中,就可以通过Spring的@Autowired类型匹配算法来匹配Map和数组类型。在这种情况下,您可以使用限定符值在同类型的集合中进行选择。
从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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://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>
在某些情况下,使用没有值的注释就足够了。当注释用于更一般的用途并且可以应用于几种不同类型的依赖项时,这将很有用。例如,您可以提供一个脱机目录,当没有Internet连接可用时可以进行搜索。首先,定义简单的批注,如以下示例所示:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Offline {
}
然后将注释添加到要自动装配的字段或属性,如以下示例所示:
public class MovieRecommender {
@Autowired
@Offline
private MovieCatalog offlineCatalog;
// ...
}
<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();
}
public enum Format {
VHS, DVD, BLURAY
}
要自动装配的字段将用自定义限定符进行注释,并包括这两个属性的值:genre和format,如以下示例所示:
p
ublic 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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://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>
1.9.5。将泛型用作自动装配限定符
除@Qualifier注释外,您还可以将Java泛型类型用作隐式限定。例如,假设您具有以下配置:
@Configuration
public class MyConfiguration {
@Bean
public StringStore stringStore() {
return new StringStore();
}
@Bean
public IntegerStore integerStore() {
return new IntegerStore();
}
}
假设前面的bean实现了一个通用接口(即Store
@Autowired
private Store<String> s1; // <String> qualifier, injects the stringStore bean
@Autowired
private Store<Integer> s2; // <Integer> qualifier, injects the integerStore bean
自动装配List,Map实例和数组时,通用限定符也适用。下面的示例自动连接泛型List:
// 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;
1.9.6。使用CustomAutowireConfigurer
CustomAutowireConfigurer
是一个BeanFactoryPostProcessor
,即使您没有使用Spring的@Qualifier
注释来注释您自己的自定义限定符注释类型,也可以使用它。以下示例显示如何使用CustomAutowireConfigurer:
<bean id="customAutowireConfigurer"
class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>example.CustomQualifier</value>
</set>
</property>
</bean>
AutowireCandidateResolver
通过以下方式确定自动装配候选对象:
- 每个bean定义的
autowire-candidate
值 <beans/>
元素上可用的任何default-autowire-candidates
模式@Qualifier
注解以及在CustomAutowireConfigurer
中注册的所有自定义注解的存在
当有多个bean可以作为自动装配候选者时,确定“首选”的步骤如下:如果候选者中恰好有一个bean定义将primary
属性设置为true
,则将其选中。
???怎么使用
1.9.7。用@Resource注入
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Resource(name="myMovieFinder")
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
如果未明确指定名称,则默认名称是从字段名称或setter方法派生的。如果是字段,则采用字段名称。在使用setter方法的情况下,它采用bean属性名称。
注释提供的名称由CommonAnnotationBeanPostProcessor
解析为bean名称。 如果您明确配置Spring的SimpleJndiBeanFactory
,则可以通过JNDI解析名称。 但是,我们建议您依赖默认行为,并使用Spring的JNDI查找功能来保留间接级别。
在@Resource
未指定任何显式名称的特例中,并且类似于@Autowired,@Resource查找首选类型匹配而不是特定的命名bean,并解析众所周知的可解析依赖项:BeanFactory
,ApplicationContext
,ResourceLoader
,ApplicationEventPublisher
和MessageSource
接口。
因此,在以下示例中,customerPreferenceDao
字段首先查找名为customerPreferenceDao
的bean,然后回退到CustomerPreferenceDao
类型的主类型匹配项:
public class MovieRecommender {
@Resource
private CustomerPreferenceDao customerPreferenceDao;
@Resource
private ApplicationContext context;
public MovieRecommender() {
}
// ...
}
1.9.8。使用@Value
@Value
通常用于注入外部属性:
@Component
public class MovieRecommender {
private final String catalog;
public MovieRecommender(@Value("${catalog.name}") String catalog) {
this.catalog = catalog;
}
}
@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig { }
catalog.name=MovieCatalog
Spring提供了一个默认的宽松内嵌值解析器。它将尝试解析属性值,如果无法解析,则将注入属性名称(例如${catalog.name}
)作为值。如果要严格控制不存在的值,则应声明一个PropertySourcesPlaceholderConfigurer
bean,如以下示例所示:
@Configuration
public class AppConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
当使用JavaConfig配置PropertySourcesPlaceholderConfigurer
,该@Bean方法必须是static
。
如果${}
无法解析任何占位符,则使用上述配置可确保Spring初始化失败。也可以使用类似setPlaceholderPrefix
,setPlaceholderSuffix
或setValueSeparator
方法来自定义占位符。
Spring Boot默认配置一个PropertySourcesPlaceholderConfigurer
bean,它将从application.properties
和application.yml
文件中获取属性。参考org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
。
Spring提供的内置转换器支持允许自动处理简单的类型转换(例如转换为Integer或int)。多个逗号分隔的值可以自动转换为String数组。
可以提供默认值:
public MovieRecommender(@Value("${catalog.name:defaultCatalog}") String catalog) {
this.catalog = catalog;
}
Spring BeanPostProcessor
使用ConversionService
幕后处理将@Value
里的String值转换为目标类型。如果要为自己的自定义类型提供转换支持,则可以提供自己的 ConversionServicebean实例,如以下示例所示:
@Configuration
public class AppConfig {
@Bean
public ConversionService conversionService() {
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
conversionService.addConverter(new MyCustomConverter());
return conversionService;
}
}
当@Value
包含SpEL表达式时,该值将在运行时动态计算,如以下示例所示:
public MovieRecommender(@Value("#{systemProperties['user.catalog'] + 'Catalog' }") String catalog) {
this.catalog = catalog;
}
SpEL还可以使用更复杂的数据结构:
public MovieRecommender(@Value("#{{'Thriller': 100, 'Comedy': 300}}") Map<String, Integer> countOfMoviesPerCatalog) {
this.countOfMoviesPerCatalog = countOfMoviesPerCatalog;
}
1.9.9。使用@PostConstruct和@PreDestroy
CommonAnnotationBeanPostProcessor
不仅支持了@Resource注解,还支持JSR-250的生命周期注解:javax.annotation.PostConstruct
和javax.annotation.PreDestroy
。在Spring 2.5中引入了对这些注释的支持,为初始化回调和销毁回调中描述的生命周期回调机制提供了一种替代方法。假设 在Spring ApplicationContext中注册了CommonAnnotationBeanPostProcessor
,在生命周期中与相应的Spring生命周期接口方法或显式声明的回调方法在同一点调用带有这些批注之一的方法。 在以下示例中,缓存在初始化时预先填充,并在销毁时清除:
public class CachingMovieLister {
@PostConstruct
public void populateMovieCache() {
// populates the movie cache upon initialization...
}
@PreDestroy
public void clearMovieCache() {
// clears the movie cache upon destruction...
}
}
与@Resource
一样,@PostConstruct
和@PreDestroy
注解类型是JDK 6到8的标准Java库的一部分。但是,整个javax.annotation
包与JDK 9中的核心Java模块分离,并最终在JDK 11中删除了。 如果需要,现在需要通过Maven Central获取javax.annotation-api
工件,只需像其他任何库一样将其添加到应用程序的类路径中即可。