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"
};
}
}
2 @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容器中,而不是手动注入。
步骤:
- (准备框架)自己写一个简单的框架:sculmy-codeutil
- (完成自动配置模块)创建 itcast-spring-boot-autoconfigure 模块
- (完成starter模块)创建 itcast-spring-boot-starter 模块
- (install)将框架、自动配置模块、starter模块安装到本地仓库
- (测试效果)测试模块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();
}
}