@Импортировать аннотацию
@ImportАннотации предоставляются и в XML<import/>Эквивалентная функциональность элемента, которая реализует один или несколько импортированных классов конфигурации.@ImportТо есть его можно использовать в классе или в качестве мета-аннотации.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
* or regular component classes to import.
*/
Class<?>[] value();
}
В аннотации только одинvalue();. Поддержка импорта@ConfigurationАннотированный класс конфигурации, реализующийImportSelectorкласс, реализация интерфейсаImportBeanDefinitionRegistrarкласс интерфейса и обычный@componentДобрый.
Использовать как мета-аннотацию
@ImportМожет использоваться как мета-аннотация, которую можно найти в@ImportНаследование инкапсулирует слой. Насколько я понимаю, это не будет раскрывать детали моей внутренней реализации внешнему миру (используя сторону).
Например: напр.@EnableAspectJAutoProxyаннотация.
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
@EnableAspectJAutoProxyдолжна быть@ImportЭта мета-аннотация отмечает, что мы (программисты), используя@EnableAspectJAutoProxyЧтобы открыть AspectJAutoProxy и нижний слой Spring через@ImportПредставляем соответствующую конфигурацию для достижения класса.
Импортировать класс, реализующий интерфейс ImportSelector.
Давайте взглянемImportSelectorинтерфейс, который имеет только один метод:
public interface ImportSelector {
String[] selectImports(AnnotationMetadata importingClassMetadata);
}
ImportSelector, селектор ввода. Этот интерфейс используется для выбора классов конфигурации для импорта в зависимости от заданных условий.
Например: напр.@EnableTransactionManagementаннотация.
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
существует@EnableTransactionManagementиспользуется в аннотации@Import(TransactionManagementConfigurationSelector.class)аннотация, котораяTransactionManagementConfigurationSelectorкласс реализованImportSelectorинтерфейс.
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
default:
return null;
}
}
}
Внутренняя логика реализации метода также очень проста, т.е.AdviceModeИмпортируйте различные классы конфигурации для реализации управления транзакциями.
Импортировать класс, реализующий интерфейс ImportBeanDefinitionRegistrar.
ImportBeanDefinitionRegistrarВ интерфейсе тоже только один метод:
public interface ImportBeanDefinitionRegistrar {
void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}
Этот интерфейс позволяет нам регистрировать дополнительные аннотации по запросу на основе заданных метаданных аннотаций.BeanDefinition.
Например: напр.@EnableAspectJAutoProxyаннотация.
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
@EnableAspectJAutoProxyАннотация представляетAspectJAutoProxyRegistrar.classкласс, этот класс реализованImportBeanDefinitionRegistrarинтерфейс.
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
registerBeanDefinitionsпозвонил вAopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);метод, этот метод проходит вBeanDefinitionRegistry registryзарегистрирован вBeanDefinition. зарегистрированBeanDefinitionПосле этого Spring создаст экземпляр Bean, чтобы получить роль AspectJAutoProxy.
Импортировать класс @Configuration
этот раз@ImportНаиболее распространенным является способ использования. Мы можем разделить класс конфигурации, а затем импортировать соответствующую конфигурацию по мере необходимости в программу.
Например: напр.@EnableRetryаннотация.
Используйте эту аннотацию, чтобы включить функцию повтора.
@EnableAspectJAutoProxy(proxyTargetClass = false)
@Import(RetryConfiguration.class)
public @interface EnableRetry {
Он импортируется внутрьRetryConfigurationЭтот класс конфигурации.
Интерфейс ImportAware
ImportAwareИнтерфейс требуется и@ImportИспользуется вместе. существует@ImportПри использовании в качестве мета-аннотации передать@ImportЕсли импортированный класс конфигурации реализованImportAwareИнтерфейс может получить конфигурацию данных, импортированную в интерфейс класса конфигурации. Это немного запутанно, давайте перейдем непосредственно к коду.
Например:@EnableAsyncаннотация.
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {
//AsyncConfigurationSelector源码
public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
@Override
@Nullable
public String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {ProxyAsyncConfiguration.class.getName()};
case ASPECTJ:
return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
default:
return null;
}
}
}
Использовать по умолчаниюAdviceModeзаPROXY, импортныйProxyAsyncConfigurationДобрый.
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {
@Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
bpp.setAsyncAnnotationType(customAsyncAnnotation);
}
if (this.executor != null) {
bpp.setExecutor(this.executor);
}
if (this.exceptionHandler != null) {
bpp.setExceptionHandler(this.exceptionHandler);
}
bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
return bpp;
}
}
существуетProxyAsyncConfigurationизasyncAdvisorметод получения@EnableAsyncНекоторые настройки по значению, например:this.enableAsync.getBoolean("proxyTargetClass"),this.enableAsync.<Integer>getNumber("order").
this.enableAsyncэто его родительский классAbstractAsyncConfigurationхарактеристики.AbstractAsyncConfigurationДостигнутоImportAwareинтерфейс, так что вы можете получить@EnableAsyncинформация о.
// AbstractAsyncConfiguration#setImportMetadata 源码
public void setImportMetadata(AnnotationMetadata importMetadata) {
this.enableAsync = AnnotationAttributes.fromMap(
importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false));
if (this.enableAsync == null) {
throw new IllegalArgumentException(
"@EnableAsync is not present on importing class " + importMetadata.getClassName());
}
}
Может быть, этот пример немного сложен, есть немного более простой пример:EnableRedisHttpSession. В связи с этим читатели могут просмотреть исходный код для отладки и изучения.
Спасибо, что обратите внимание на общественное число WeChat: