java的 import注解_认识Spring中的@Import注解

简介

在Spring 3.0,Spring引入了@Import注解,允许通过JavaConfig导入一个或多个类作为 Spring Bean,这些类不需要标注 Spring 模式注解。

Spring 模式注解:

@Componet、@Service、@Controller、@Repository、@Configuration

@Import的源码

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Import {

/** * {@link Configuration @Configuration}, {@link ImportSelector}, * {@link ImportBeanDefinitionRegistrar}, or regular component classes to import. */

Class>[] value();

}

可以看出@Import可以配合 Configuration , ImportSelector, ImportBeanDefinitionRegistrar 来使用,也可以导入普通的类。

@Import只允许放到类上面,不能放到方法上。

准备

搭建Spring环境,创建启动类``:

public class MyApplication {

public static void main(String[] args) {

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.haan");

String[] beanDefinitionNames = context.getBeanDefinitionNames();

Stream.of(beanDefinitionNames)

.forEach(s -> System.out.println(s));

}

}

导入普通的类

新建两个类,TestService1.class 和TestService2.class:

public class TestService1 {

public void print(){

System.out.println("this is service01 !");

}

}

public class TestService2 {

public void print(){

System.out.println("this is service02 !");

}

}

定义 MyImportConfiguration类,注解@Configuration,@Import,@Import 传参values={Test}value = {TestService1.class,TestService2.class}:

@Import(value = {TestService1.class,TestService2.class})

@Configuration

public class MyImportConfiguration {

}

执行main函数,输出日志如下:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor

org.springframework.context.annotation.internalAutowiredAnnotationProcessor

org.springframework.context.annotation.internalCommonAnnotationProcessor

org.springframework.context.event.internalEventListenerProcessor

org.springframework.context.event.internalEventListenerFactory

myImportConfiguration

com.haan.TestService1

com.haan.TestService2

Process finished with exit code 0

我们看到,TestService1.class和TestService2.class 都被实例为Spring Bean 了。但是这种方式有一些问题,那就是只能使用类的无参构造方法来创建bean,对于有参数的构造方法就无能为力了。

结合ImportSelector接口

我们先看一下ImportSelector接口:

public interface ImportSelector {

// Select and return the names of which class(es) should be imported based on

String[] selectImports(AnnotationMetadata importingClassMetadata);

// Return a predicate for excluding classes from the import candidates

@Nullable

default Predicate getExclusionFilter() {

return null;

}

}

我们注释可以大概了解到方法selectImport(...)返回的classNames 将会被import,实例为Spring Bean。方法getExclusionFilter()将返回一个Predicate, 后续将通过该Predicate 将候选的类排除,不进行import。

我们这里定义类MyImportSellectorImpl实现接口ImportSelector:

public class MyImportSelectorImpl implements ImportSelector {

@Override

public String[] selectImports(AnnotationMetadata annotationMetadata) {

return new String[]{TestService3.class.getName(),TestService4.class.getName()};

}

}

我们这里返回了类TestService3 和 TestService4的类名称,TestService3 和 TestService4是我们新创建的两个类:

public class TestService3 {

public void print(){

System.out.println("this is service03 !");

}

}

public class TestService4 {

public void print(){

System.out.println("this is service04 !");

}

}

然后,我们修改下我们的MyImportConfiguration类,将MyImportSelectorImpl添加到@Import的参数中:

@Import(value = {TestService1.class,TestService2.class,MyImportSelectorImpl.class})

@Configuration

public class MyImportConfiguration {

}

再次执性程序,得到控制台输出:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor

org.springframework.context.annotation.internalAutowiredAnnotationProcessor

org.springframework.context.annotation.internalCommonAnnotationProcessor

org.springframework.context.event.internalEventListenerProcessor

org.springframework.context.event.internalEventListenerFactory

myImportConfiguration

com.haan.TestService1// 普通类导入

com.haan.TestService2 // 普通类导入

com.haan.TestService3// 结合ImportSelector 接口

com.haan.TestService4 // 结合ImportSelector 接口

Process finished with exit code 0

通过输出,我们发现类TestService3 和 TestService4也被实例为 Spring Bean 了。

结合ImportBeanDefinitionRegistrar接口

ImportBeanDefinitionRegistrar接口的源码如下:

public interface ImportBeanDefinitionRegistrar {

// Register bean definitions as necessary based on the given annotation metadata of

default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,

BeanNameGenerator importBeanNameGenerator) {

registerBeanDefinitions(importingClassMetadata, registry);

}

// Register bean definitions as necessary based on the given annotation metadata of

default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

}

}

AnnotationMetadata:通过这个参数可以拿到类的元数据信息

BeanDefinitionRegistry:通过这个参数可以操作IOC容器

BeanNameGenerator : 通过这个可以操作Bean 名称生成策略

我们可以使用一个类来实现这个接口:

public class MyImportBeanDefinitionRegistrarImpl implements ImportBeanDefinitionRegistrar {

@Override

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(TestService5.class);

registry.registerBeanDefinition("testService060001",beanDefinitionBuilder.getBeanDefinition());

}

}

其中的TestService5 是我们新创建的一个类:

public class TestService5 {

public void print(){

System.out.println("this is service05 !");

}

}

然后,我们修改下我们的MyImportConfiguration类,将MyImportBeanDefinitionRegistrarImpl添加到@Import的参数中:

@Import(value = {TestService1.class,TestService2.class,MyImportSelectorImpl.class,MyImportBeanDefinitionRegistrarImpl.class})

@Configuration

public class MyImportConfiguration {

}

再次执性程序,得到控制台输出:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor

org.springframework.context.annotation.internalAutowiredAnnotationProcessor

org.springframework.context.annotation.internalCommonAnnotationProcessor

org.springframework.context.event.internalEventListenerProcessor

org.springframework.context.event.internalEventListenerFactory

myImportConfiguration

com.haan.TestService1

com.haan.TestService2

com.haan.TestService3

com.haan.TestService4

testService060001// 结合ImportBeanDefinitionRegistrar

Process finished with exit code 0

我们发现类TestService5 也被实例为 Spring Bean 了, 且 Bean Name 可以自定义。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值