擅长SpringBoot的六花同学(三)

本文详细介绍了SpringBoot中的自动配置,包括如何使用Condition注解进行Bean的选择性创建,如ClassCondition和ConditionOnClass的使用,以及如何控制Jedis的加载。同时探讨了内置服务器的切换,如从Tomcat切换到Jetty,以及Bean的导入和注册方法。
摘要由CSDN通过智能技术生成

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);
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值