SpringBoot自动配置
Condition
Condition是Spring4.0增加的条件判断功能,通过这个可以实现选择性的创建Bean操作
@Configuration
public class UserConfig {
@Bean
//这个ClassCondition类是自己定义的,判断条件由这个类中重写的matches方法完成
@Conditional(ClassCondition.class)
public User user(){
return new User();
}
}
public class ClassCondition implements Condition {
// 返回false就表示条件不满足 不会创建
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return false;
}
}
自定义注解实现condition
@Configuration
public class UserConfig {
@Bean
//这个ClassCondition类是自己定义的,判断条件由这个类中重写的matches方法完成
// @Conditional(ClassCondition.class)
@ConditionOnClass("redis.clients.jedis.Jedis")
public User user(){
return new User();
}
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME) // 注解生效实际
@Documented //生成文档
@Conditional(ClassCondition.class)
public @interface ConditionOnClass {
String[] value();
}
public class ClassCondition implements Condition {
/**
*
* @param context 上下文对象,用于获取环境,IOC容器,classloader对象
* @param metadata 注解的元对象 可以用于获取注解定义的属性值
* @return
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(ConditionOnClass.class.getName());
String[] value = (String[]) annotationAttributes.get("value");
//用于判断redis.clients.jedis.Jedis.class文件是否存在;
boolean flag = true;
try {
for (String className : value) {
Class<?> cls = Class.forName(className);
}
} catch (ClassNotFoundException e) {
flag = false;
}
return flag;
}
}
切换内置Web服务器
<!-- 排除tomcat的依赖 -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入jetty依赖,内部同样使用condition实现 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
引入其他module里面的bean
<dependency>
<groupId>com.example</groupId>
<artifactId>enable-other</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
Enable注解原理/导入Bean
/**
* @ComponentScan:扫描的范围是当前引导类及其子包
* 1.可以通过@ComponentScan扫描
* 2.可以使用@Import注解,加载类
* 3.对Import注解进行封装。其实和方法2差不多
*
* Enable*注解一般用来开启某些功能
*/
// 这个里面包含了一个Scan的注解,其实就是一个spring配置的集合
@SpringBootApplication
// // 增加扫描
// @ComponentScan(basePackages = {"com.itheima"})
// @Import(UserConfig.class)
@EnableUser
// 可以通过import导入单个bean
//@Import(Role.class)
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);
}
}
@Configuration //也可以是bean
public class UserConfig {
@Bean
public User user(){
return new User();
}
}
其他可以把需要单独导入的bean写到一个类中,通过import导入实现
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.itheima.domain.User","com.itheima.domain.Role"};
}
}
最后一种方法
通过BeanDefinition注册器实现Bean的注入,同样使用Import
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);
}
}