介绍
Spring 提倡使用注解和配置类来完成 Bean 的装配,而配置类就是全面取代 xml配置文件 的一种方式
推荐使用扫描和配置类开发项目
导入(装配) Bean 的三种方:
- @ComponentScan(扫描)
- @Import(导入/整合)
- @Bean(配置类中装配)
类注解
@Configuration
用于标识一个类为合法的 Spring配置类
不加 @Configuration 就是 Lite,加 @Configuration 就是 Full
Lite[非代理](简单、迷你):性能最高,不使用代理
Full[代理](全面):使用代理
只有加了 @Configuration 才享有完整的容器功能,否则只有 @Bean 功能
Full底层(猜测):对配置类进行动态代理,对所有方法增强(判断是否有@Bean注解,选择执行)
代理的作用:使用者不直接于被使用者联系,而是通过代理去联系,同时代理可以进行一些额外的操作(比如:返回存储的对象而不执行new对象)
@ComponentScan(扫描)
用于扫描指定的包,装配相关的Bean,对应xml中的扫描
@Import(导入/整合)
-
导入普通的 Bean(不推荐)
比如:@Import({UserController.class, UserServiceImpl.class}) -
导入其他配置类(推荐)
在项目中模块化配置类,包括 mvc 的配置类、mybatis 配置类、Redis 配置类、RabbitMQ 配置类等等
那么可以在一个总配置类中导入其他这些配置类进行合并,
这样维护性扩展性更强
比如:@Import({MvcConfig.class,MybatisConfig.class}) -
选择性导入(推荐)
即按照指定的逻辑来导入相关的类
这种方式需要自定义一个或者多个导入选择器交给 spring 执行,
而导入选择器的目的是找到并返回完整类名的集合(不管使用什么手段)
比如:@Import(AnnoImportSelector.class)public class AnnoImportSelector implements ImportSelector { /** * 自定义导入逻辑 * @param importingClassMetadata * @return 返回值就是所有需要导入的类的完整类名 */ @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { // 需要导入的类的完整类名的集合 List<String> classNameList = new ArrayList<>(); /* 扫描(不管使用什么方法,只要能把完整类名放到集合就可以) */ return StringUtils.toStringArray(classNameList); } }
@PropertySource
将 properties 文件的属性注入到配置类的字段中,使用 @Value 注入
比如
@PropertySource("jdbc.properties")
class 类{}
方法注解
@Bean
用于标识 Bean,而其中方法名代表 Bean 的 Id,返回的是对应的实现类
对应 xml配置文件 中的<bean id="xx"/>
还可以通过name属性指定bean的别名,比如@Bean(name = {"aa","bb"})
@Scope
声明作用域
@Value
前提是所有 @@PropertySource
使用 @Value 注解结合 spel 表达式进行值注入,也就是将 properties 文件中的属性值注入到当前字段中
@Value("${jdbc.driver}")
需要注入其他依赖的两种方式
通过参数注入(Spring进行注入)
@Bean
public UserController userController(UserService userService){
return new UserController(userService);
}
通过其他的bean方法注入
@Bean
public UserController userController(){
return new UserController(userService());
}
案例
@Configuration
@ComponentScan(basePackages = "edu.nf.ch13")
public class AppConfig {
/**
* 除了使用@Component、@Service、@Controller
* @Respository注解来装配Bean以外,还可以使用
* @Bean注解在配置类中装配Bean,这种方式很类似
* 在xml中配置一个个的<bean id="xx"/>,
* 用了@Bean注解后默认标注的方法名就是Bean的id,
* 还可以通过name属性指定bean的别名
*
* @return
*/
//@Bean(name = {"aa","bb"})
@Bean
public UserService userService() {
return new UserServiceImpl();
}
/**
* 当需要注入其他Bean的时候,有两种方式
* 方式一:通过参数实现注入
* 方式二:通过调用方bean方法实现注入
*
* @Scope注解还可以声明在Bean方法上来设置Bean的作用域
* @return
*/
@Bean
@Scope("prototype")
public UserController userController() {
return new UserController(userService());
}
}