@Import可以导入bean或者@Configuration修饰的配置类。如果配置类在标准的springboot的包结构下,就是SpringbootApplication启动类在包的根目录下,配置类在子包下。就不需要使用@Import导入配置类,如果配置类在第三方的jar下,我们想要引入这个配置类,就需要@Import对其引入到工程中才能生效。因为这个时候配置类不再springboot默认的扫描范围内。

@Import 相当于Spring xml配置文件中的<import />

@Import的几种用法:

使用方法一:导入普通类

1.1 把普通的类用@Import导入之后成为一个bean。这个类并未使用@Service、@Component将其创建为bean。

@Getter
@Setter
public class MySqlConn {
    private String driverClass = "xxxx";
    private String url = "jdbc:mysql://localhost:3306/mydb";
    private String userName = "root";
    private String password = "root";

}

1.2 在springboot的启动类@Import这个类,这个类就可以被其他类当做bean来引用。

@SpringBootApplication
@Import({MySqlConn.class})
public class SpringBootApplication1 {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootApplication1.class, args);
    }

}

1.3 测试,定义一个controller来测试,调用这个通过@Import方式导入的bean

@RestController
@RequestMapping("test")
public class RestTestController {
    @Autowired
    private MySqlConn mySqlConn;

    @GetMapping("common")
    public String commonBean() {
        String jsonResult = "";
        ObjectMapper mapper = new ObjectMapper();
        try {
            jsonResult = mapper.writeValueAsString(mySqlConn);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return jsonResult;
    }
}

使用方法二:和@Configuration搭配使用

@Import被用来整合@Configuration注解中定义的bean配置。

2.1 定义一个配置类@Configuration,配置类中定义了一些bean。下面的代码中可以看到我们定义的bean是MySqlServerBean。

@Configuration
public class MySqlConfig {
    @Bean
    public MySqlServerBean getBean() {
        MySqlServerBean bean = new MySqlServerBean();
        bean.setUserName("lyj");
        return bean;
    }
}

2.2 在启动类中@import这个配置类:

@SpringBootApplication
@Import(MySqlConfig.class)
public class SpringBootApplication3 {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootApplication3.class, args);
    }
}

2.3 测试,定义一个controller,我们看到在controller中就可以直接使用在MySqlConfig中定义MySqlServerBean了。

@RestController
@RequestMapping("test")
public class RestTestController {

    @Autowired
    private MySqlServerBean mySqlServerBean;

    @GetMapping("mysql")
    public String mysql() {
        String jsonResult = "";
        ObjectMapper mapper = new ObjectMapper();
        try {
            jsonResult = mapper.writeValueAsString(mySqlServerBean);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return jsonResult;
    }
}

使用方法三:在配置类上导入

在配置类上通过@Import直接导入类,也可以被引用成bean。

3.1 定义一个普通的类

@Getter
@Setter
public class PoolBean {
    private String redisHost = "127.0.0.1";
    private String redisPort = "6379";
    private String redisDb = "0";
}

3.2 在配置类上导入这个类

@Configuration
@Import({PoolBean.class})
public class RedisConfig {
    @Bean
    public RedisClusterBean getHost() {
        return new RedisClusterBean();
    }
}

3.3 测试,启动项目,在controller直接引用这个PoolBean。

@SpringBootApplication
public class SpringBootApplication2 {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootApplication2.class, args);
    }
}
@RestController
@RequestMapping("test")
public class RestTestController {
    @Autowired
    private PoolBean poolBean;

    @GetMapping("pool")
    public String poolBean() {
        String jsonResult = "";
        ObjectMapper mapper = new ObjectMapper();
        try {
            jsonResult = mapper.writeValueAsString(poolBean);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return jsonResult;
    }

}

使用方法四:和ImportSelector搭配使用

新建一个Maven工程,pom.xml的类型是jar,我们写一个第三方的jar包,用来引用到我们的主工程中,进行ImportSelector的示例使用。工程结构大概如下图:

spring boot 每个模块的引用 spring boot @import_json

4.1 在third-part功能中,我们先定义一个config

@Configuration
public class AppConfig {
    @Bean
    public Student studentBean() {
        Student student = new Student();
        student.setId(10);
        student.setName("王某");
        return student;
    }
}

4.2 自定义一个SpringStartSelector实现接口ImportSelector,BeanFactoryAware。重写selectImports()方法和setBeanFactory()方法。这里在程序启动的时候会先运行setBeanFactory()方法,我们可以在这里获取到beanFactory。selectImports()方法回了了AppCoinfig的全类名。

public class SpringStartSelector implements ImportSelector, BeanFactoryAware {
    private BeanFactory beanFactory;

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        System.out.println("importingClassMetaData:" + importingClassMetadata);
        System.out.println("beanFactory:" + beanFactory);
        return new String[]{AppConfig.class.getName()};
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
}

4.3 自定义一个注解EnableSpringStudy,在这个注解使用@Import()导入4.2中自定义的SpringStartSelector

@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
@Import(SpringStartSelector.class)
public @interface EnableSpringStudy {
}

4.4 完成之后我们把 third-part项目打成jar包,在主项目的pom文件中引入

<dependency>
    <groupId>com.win.world</groupId>
    <artifactId>third-part</artifactId>
    <version>1.0.0</version>
</dependency>

4.5 主项目中在SpringBoot的启动类上使用我们4.3中自定义的注解。然后测试我们能否获取到AppConig中的bean。

@SpringBootApplication
@EnableSpringStudy
public class SpringBootApplication4 {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootApplication4.class, args);
    }
}

测试能否获取到AppConfig中的bean

@RestController
@RequestMapping("test")
public class RestTestController {
    @Autowired
    private Student student;

    @GetMapping("selector")
    public String selector() {
        String jsonResult = "";
        ObjectMapper mapper = new ObjectMapper();
        try {
            jsonResult = mapper.writeValueAsString(student);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return jsonResult;
    }

}

使用方法五:和ImportBeanDefinitionRegistrar搭配使用

ImportBeanDefinitionRegistrar接口也是Spring的扩展点之一,它可以支持我们自己写的代码封装成BeanDefinition对象;实现此接口的类回调postProcessBeanDefinitionRegistry方法,注册到Spring容器中。把bean注入到Spring容器不止有@Service @Component

5.1 我们先定义一个MyImportBeanDefinitionRegistrar类实现ImportBeanDefinitionRegistrar接口,并通过重写registerBeanDefinitions()来定义一个bean

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        BeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClassName(PoolBean.class.getName());
        MutablePropertyValues property = beanDefinition.getPropertyValues();
        property.addPropertyValue("redisHost", "localhost");
        property.addPropertyValue("redisPort", "6377");
        //这里注册bean
        registry.registerBeanDefinition("poolBean", beanDefinition);
    }
}

5.2 定义一个配置类,@Import导入5.1的自定义类

@Configuration
@Import(MyImportBeanDefinitionRegistrar.class)
public class RegistrarConfig {
}

5.3 启动项目并测试自己在registerBeanDefinitions()方法中创建的bean PoolBean是否成功

@SpringBootApplication
public class SpringBootApplication5 {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootApplication5.class, args);
    }
}
@RestController
@RequestMapping("test")
public class RestTestController {
    @Autowired
    private PoolBean poolBean;

    @GetMapping("registrar")
    public String registrarTest() {
        String jsonResult = "";
        ObjectMapper mapper = new ObjectMapper();
        try {
            jsonResult = mapper.writeValueAsString(poolBean);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return jsonResult;

    }

}

参考:

  【1】一分钟学会Spring注解之@Import注解,https://blog.51cto.com/4247649/2118354