4 SpringBoot中的自动配置

1 将对象注入Spring IOC容器的4种方式

需求:把如下这个实现类导入到spring容器中,以后每次使用这个对象时,就不用new了,而是用spring工厂来提供。

public class UserServiceImpl implements UserService {
    @Override
    public void findAll() {
        System.out.println("假装我是一个service层的实现类方法===");
    }
}

在启动引导类中,写了如下的代码来验证该对象是否被成功导入到Spring IOC容器中:

@SpringBootApplication
public class Springboot03AnnotationImportApplication {
    public static void main(String[] args) {
        //SpringApplication.run方法返回值是spring的容器对象
        ConfigurableApplicationContext context = SpringApplication.run(Springboot03AnnotationImportApplication.class, args);
        //从容器中获取对象
        UserService userService = context.getBean(UserService.class);
        System.out.println(userService);
    }
}

下面开始介绍4种方式,注意:以上4种方法不能混用!

方式1:直接在这个类上用@Service修饰

这种方式是最常用的方式,当然,本次讲解的重点在于后三种方式。

@Service
public class UserServiceImpl implements UserService {
    @Override
    public void findAll() {
        System.out.println("假装我是一个service层的实现类方法===");
    }
}

方式2:直接把这个类注入到IOC容器中,借助@Import注解

@Import(UserServiceImpl.class)
@SpringBootApplication
public class Springboot03AnnotationImportApplication {
    public static void main(String[] args) {
        //SpringApplication.run方法返回值是spring的容器对象
        ConfigurableApplicationContext context = SpringApplication.run(Springboot03AnnotationImportApplication.class, args);
        //从容器中获取对象
        UserService userService = context.getBean(UserService.class);
        System.out.println(userService);
    }
}

方式3:导入一个配置类,配置类中定义一个方法来返回目标对象

自己写一个配置类,这个配置类需要 @Configuration修饰
配置类中定义的方法用 @Bean 修饰
配置类的位置随便放,最好放在组织 groupId.config文件夹下

@Configuration
public class SpringConfiguration {
   @Bean
    public UserService userService(){
        return new UserServiceImpl();
    }
}

方式4:导入ImportSelector 接口的实现类对象,把批量的类的全限定名称注入到IOC容器中

这种方法需要自己实现 ImportSelector 接口,然后把需要导入Spring IOC容器中的对象的全限定类名依次写到如下的字符串数组中。

/**
 * 批量导入对象到容器的类
 */
public class MySelectImport implements ImportSelector {
    //返回需要导入到spring容器中所有对象的全限定名称
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{
                "com.lmy.service.UserServiceImpl",
                "com.lmy.pojo.User"
        };
    }
}

@Conditionalxxx 注解的使用

在介绍@Conditionalxxx 注解前,先回顾下:@Configuration 表明,被该注解修饰的类是一个配置类,可以将对象注入到Spring的IOC容器中,这个功能上面也讲过(上面的方式3):

@Configuration
public class SpringConfiguration {
   @Bean
    public UserService userService(){
        return new UserServiceImpl();
    }
}

现在,@Bean 这个注解是直接生效的,也就是说上面代码中的userService 对象确实会注入到spring容器中,但是现在我想加个条件后再让@Bean 注解生效
于是,@Conditionalxxx 注解就出现了(xxx表示有很多种条件)

举例应用1:当我的classpath路径下存在Cat类的时候,才会注入dog对象,否则不注入。

/**
 * 配置类
 */
@Configuration
public class SpringConfiguration {
    /**
     * 当我的classpath路径下存在Cat类的时候,才会注入dog对象,否则不注入
     * 可以修饰类,也可以修饰方法
     */
    @Bean
    @ConditionalOnClass(name = "com.lmy.pojo.Cat")
    public Dog dog(){
        return new Dog();
    }
}

应用举例2:通过配置文件,控制一个注解的开启和关闭

/**
 * 配置类
 */
@Configuration
public class SpringConfiguration {
    /**
     * @ConditionalOnClass(name = "com.lmy.pojo.Cat"): 当我的classpath路径下存在Cat类的时候,才会注入dog对象,否则不注入
     * @ConditionalOnProperty(name = "spring.lmy.enable", havingValue = "true",matchIfMissing = true): 当配置文件中有这个变量,且变量“spring.lmy.enable”的值为true时,注解生效,否则不生效
     *
     * 可以修饰类,也可以修饰方法
     */
    @Bean
    @ConditionalOnProperty(name = "spring.lmy.enable", havingValue = "true",matchIfMissing = true)
    //@ConditionalOnClass(name = "com.lmy.pojo.Cat")
    public Dog dog(){
        return new Dog();
    }
}

3 动手实现自动配置

要求:

  • 自定义一个简单的框架,实现一个简单的功能
  • 在另外一个测试工程里面,导入该框架的起步依赖
  • 导入starter之后,实现简单的框架中核心对象自动注入到测试工程的Spring IOC容器中,而不是手动注入。

步骤:

  1. (准备框架)自己写一个简单的框架:sculmy-codeutil
  2. (完成自动配置模块)创建 itcast-spring-boot-autoconfigure 模块
  3. (完成starter模块)创建 itcast-spring-boot-starter 模块
  4. (install)将框架、自动配置模块、starter模块安装到本地仓库
  5. (测试效果)测试模块springboot04-test-my-auto-configuration

实现:

步骤1:(准备框架)自己写一个简单的框架:sculmy-codeutil

/**
 * 代码生成器的核心类:帮助我们生成所有的通用代码
 */
public class CodeUtils {
    public void generatorCode(){
        System.out.println("这是我要实现的一个功能,什么都可以,功能已经生成");
    }
}

 

步骤2:(完成自动配置模块)创建 itcast-spring-boot-autoconfigure 模块

  • 定义代码生成器核心对象的配置类信息
  • 在META-INF/spring.factories扩展自动配置(@EnableAutoConfiguration 的全类名=配置类的全类名)
/**
 * codeutil的自动配置类
 * 帮我们注入CodeUtils对象到spring容器中,谁导入starter坐标,就注入到哪里去
 * @ConditionalOnClass 注解增加了判断条件:只有存在CodeUtils类的时候配置类才生效
 */
@Configuration
@ConditionalOnClass(name = "cn.sculmy.utils.CodeUtils")
public class AutoConfiguration {
    /**
     * 自动配置类帮助我们把 CodeUtils对象注入到spring容器中,这个操作不用我们自己来干!
     * @ConditionalOnProperty 配置文件控制注解是否生效,默认是生效的
     */
    @Bean
    @ConditionalOnProperty(name = "spring.sculmy.enable", havingValue = "true", matchIfMissing = true)
    CodeUtils codeUtils(){
        return new CodeUtils();
    }
}
#配置当前自动配置类的加载
#@EnableAutoConfiguration 的全类名=配置类的全类名
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.sculmy.config.AutoConfiguration

 步骤3:(完成starter模块)创建 itcast-spring-boot-starter 模块

starter模块很简单,就是一个pom文件,在里面导入框架、自动配置模块的坐标,无需导入其他任何坐标。

 步骤4:(install)将框架、自动配置模块、starter模块安装到本地仓库

步骤5:(测试效果)测试模块springboot04-test-my-auto-configuration

测试结果显示:在测试类中我们没有专门写代码把CodeUtils对象注入到容器中,而是我写的自动配置帮我注入的!

@SpringBootApplication
public class SculmySpringBootTestApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SculmySpringBootTestApplication.class, args);
        //测试:自己写的,从外部导入进来的CodeUtils类能不能用,注意:我没有把对象注入到容器,而是我写的自动配置帮我注入的!
        CodeUtils utils = context.getBean(CodeUtils.class);
        utils.generatorCode();
    }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值