目录
一.Enable*注解
1.Enable*注解概述
SpringBoot中提供了很多Enable开头的注解,这些注解都是勇于动态启用某些功能的,而其底层原理是使用@Import注解导入一些配置类,实现Bean的动态加载。
下面通过一个小案例来了解Enable*注解吧~
自定义实现一个Enable*注解,实现bean的注入
实现步骤:
1.创建两个模块enable模块依赖于enable-other
2.enbale模块依赖
<dependency>
<groupId>com.tangbb</groupId>
<artifactId>enable-other</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
3.enable-other模块中新建User和Role实体类
public class Role {
}
public class User {
}
4.enable-other模块中新建UserConfig
import com.tangbb.enableother.domain.Role;
import com.tangbb.enableother.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfig {
@Bean
public User user() {
return new User();
}
@Bean
public Role role() {
return new Role();
}
}
5.enable-other模块中新建注解EnableUser
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(UserConfig.class)//使用import注解导入刚刚新建的配置类
public @interface EnableUser {
}
6.enable模块中测试
import com.tangbb.enableother.config.EnableUser;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
@EnableUser
public class EnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(EnableApplication.class, args);
Object user = context.getBean("user");
System.out.println(user);
Object role = context.getBean("role");
System.out.println(role);
}
}
拓展(重要:涵盖import注解的四种用法):
import com.tangbb.enableother.config.EnableUser;
import com.tangbb.enableother.config.MyImportBeanDefinitionRegistrar;
import com.tangbb.enableother.config.MyImportSelector;
import com.tangbb.enableother.config.UserConfig;
import com.tangbb.enableother.domain.Role;
import com.tangbb.enableother.domain.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
@SpringBootApplication
//方案1:通过自定义Enable注解 实现bean的注入
//@EnableUser
//方案2:通过自定义添加包的扫描路径 实现bean的注入
//@ComponentScan("com.tangbb.enableother.config")
//方案3:通过下面import注解的四种方式 实现bean的注入
//@Import(User.class)
//@Import(UserConfig.class)
//@Import(MyImportSelector.class)
//@Import({MyImportBeanDefinitionRegistrar.class})
public class EnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(EnableApplication.class, args);
/**
* 以下几种注解的方式可以通过这个方式获取bean
* //@EnableUser
* //@ComponentScan("com.tangbb.enableother.config")
* //@Import(UserConfig.class)
* //@Import({MyImportBeanDefinitionRegistrar.class})
*/
Object user = context.getBean("user");
System.out.println(user);
Object role = context.getBean("role");
System.out.println(role);
/**
* 以下两种方式的注解必须要使用类的全限定名来获取bean否则获取不到
* @Import(User.class)
* @Import(MyImportSelector.class)
*/
// User user = context.getBean(User.class);
// System.out.println(user);
// Role role = context.getBean(Role.class);
// System.out.println(role);
}
}
二.Import注解
/**
* Import4中用法:
* 1. 导入Bean
* 2. 导入配置类
* 3. 导入ImportSelector的实现类。
* 4. 导入ImportBeanDefinitionRegistrar实现类
*/
import的前两中用法比较简单这里不再赘述。下面请看下面两种import注解的封装用法。
import的用法三: enable-other模块中新建 importSelector的实现类MyImportSelector。
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.tangbb.enableother.domain.User", "com.tangbb.enableother.domain.Role"};
}
}
import的用法四:enable-other模块中新建ImportBeanDefinitionRegistrar实现类MyImportBeanDefinitionRegistrar
import com.tangbb.enableother.domain.Role;
import com.tangbb.enableother.domain.User;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
registry.registerBeanDefinition("user", beanDefinition);
AbstractBeanDefinition role = BeanDefinitionBuilder.rootBeanDefinition(Role.class).getBeanDefinition();
registry.registerBeanDefinition("role", role);
}
}
三.ComponentScan注解
@ComponentScan 扫描范围:当前引导类所在包及其子包
每个springboot工程默认包臊面范围为当前引导类所在包及其子包。如果想要添加额外的扫描包,需要使用@ComponentScan指定扫描的路径。
如下:enable模块依赖的enable-other模块,enable模块的启动引导类如下,可以加@ComponentScan指定添加enable-other模块的包扫描