SpringBoot自动配置
Condition
实现选择性的创建Bean
项目结构
UserConfig
@Bean @Conditional(ClassCondition.class) public User user(){ return new User(); }
ClassCondition
public class ClassCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return false; } }
这里返回值为false则使用@Conditional注解的Bean不会被创建
导入jedis包
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>
@Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { boolean flag = true; try { Class<?> cls = Class.forName("redis.clients.jedis.Jedis"); } catch (ClassNotFoundException e) { flag = false; } return flag; }
从而控制Bean的选择性加载
将类的判断定义为动态的
UserConfig
@Bean @ConditionOnClass("redis.clients.jedis.Jedis") public User user(){ return new User(); }
ConditionOnClass
@Target({ElementType.TYPE, ElementType.METHOD})//可以添加到类和接口上面 @Retention(RetentionPolicy.RUNTIME)//生效时机 @Documented @Conditional(ClassCondition.class) public @interface ConditionOnClass { String[] value(); }
此时即可加载User的Bean
还可以利用获取注解属性值
@Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { boolean flag = true; Map<String,Object> map = metadata.getAnnotationAttributes(ConditionOnClass.class.getName()); String[] value = (String[]) map.get("value"); try { for(String className : value){ Class<?> cls = Class.forName(className); } } catch (ClassNotFoundException e) { flag = false; } return flag; }
@ConditionalOnProperty(name = "键名",havingValue = "键值")
当某一个键存在且键值对应,则加载
@Bean @ConditionalOnProperty(name = "rikka",havingValue = "sixFlower") public User user(){ return new User(); }
在application.yml中添加rikka: sixFlower
即可加载
@ConditialOnProperty 判断配置文件中是否有对应的属性
@ConitionalOnClass 判断环境中是否有对应的字节码文件
@ConitionalOnMissingBean 判断环境中是否有对应Bean
切换内置web服务器
SpringBoot的web环境中默认使用tomcat作为内置服务器,其实SpringBoot中提供4种内置服务器。
导入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
此时启动,服务器默认为tomcat
排除tomat依赖并导入jetty依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency>
此时使用的就是jetty了
Bean的自动加载
新建另一个项目SpringBootEnable
创建Bean
@Configuration public class UserConfig { @Bean public User user(){ return new User(); } }
尝试在其他项目导入
<dependency> <groupId>com.example</groupId> <artifactId>SpringBootEnable</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
使用注解添加扫描包路径或者利用@Import导入配置类
@ComponentScan("com.example")
@Import(UserConfig.class)
UserConfig
@Configuration public class UserConfig { @Bean public User user(){ return new User(); } }
还可以对Import进行封装
创建注解接口EnableUser
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(UserConfig.class) public @interface EnableUser { }
使用@EnableUser就可以了
@Import用法
导入Bean,并查看
@SpringBootApplication @Import(User.class) public class SpringbootInitApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(SpringbootInitApplication.class, args); User user = context.getBean(User.class); System.out.println(user); } }
因为直接导入Bean名字不确定,所以采用类型读取
导入配置类
@SpringBootApplication @Import(UserConfig.class) public class SpringbootInitApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(SpringbootInitApplication.class, args); User user = context.getBean(User.class); System.out.println(user); } }
导入ImportSelector
MyImportSelector
public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{"com.example.springbootenable.domain.User"}; } }
使用时使用@Import导入这个类
导入ImportBeanDefinitionRegistrar
MyImportBeanDefinitionRegistrar
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator){ AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition(); registry.registerBeanDefinition("user",beanDefinition);//user给Bean起名 } }
@SpringBootApplication @Import(MyImportBeanDefinitionRegistrar.class) public class SpringbootInitApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(SpringbootInitApplication.class, args); User user = context.getBean("user"); System.out.println(user); } }