1.引言
spring框架有四个基础核心:
- IoC容器
- JavaConfig
- 事件监听
- Spring factories
2.JavaConfig
早期spring玩家,一定会有一个痛点:项目规模稍微大一点,基于xml配置spring相关的bean,是一件复杂又难受的事情,因为在xml配置文件里拥有太多东西!很不幸!我就是这么过来的。
后来,为了解决这个问题,spring内部整了一个子项目:JavaConfig。基于java代码和注解(Annotation)来描述bean,以及bean之间的依赖关系。
对比来看,基于xml和JavaConfig子项目的配置
- xml配置
<bean id=xxxService class=com.xxx.XxxServiceImpl/>
- JavaConfig配置
@Configuration
public class XxxConfiguration{
@Bean
public XxxService xxxService(){
return new XxxServiceImpl();
}
}
@Bean注解相当于xml配置方式中的bean标签。@Configuration表示这是一个配置类。
你看到了,这就是JavaConfig子项目的直观例子。通过Java代码+注解的方式,实现配置模块化,和清晰度都更优于xml配置文件方式。
当然,spring给我们提供了一些常用的注解:
-
@ComponentScan注解:指定spring容器启动时,需要扫描的包下符合条件的bean,将这些bean注册到IoC容器中。它有一个basePackage属性,用于指定要扫描的包,默认从@ComponentScan注解所在的包开始扫描,你应该能理解了,为什么springboot应用启动类,通常建议放在src/main/java下了吧
-
@Component注解:标记某个类的实例bean,需要交给IoC容器管理
-
@Controller(RestController)注解:从@Component衍生的子注解,表示这是控制层bean
-
@Service注解:从@Component衍生的子注解,表示这是业务处理层bean
-
@Repository注解:从@Component衍生的子注解,表示这是数据访问层bean
-
@Import注解:当配置类之间有依赖关系时,用于导入其它配置
-
@Conditional注解:前面列举的几个注解,大家都非常熟悉!这里重点看一看@Conditional注解,它表示在满足某些条件下,才启用某些配置,或者初始化某个bean。正因为有了@Conditional注解,让我们在使用spring框架时,拥有足够的灵活性和扩展性。
举例子:
例子描述:自定义扩展Condition类,查找当前项目类是否有JdbcTemplate
// 自定义扩展Condition,查找类路径下是否有JdbcTemplate
public class MyCondition implements Condition {
@Override
public boolean matches(ConditionContext ctx, AnnotatedTypeMetadata atm) {
try {
ctx.getClassLoader().
loadClass(org.springframework.jdbc.core.JdbcTemplate);
return true;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return false;
}
}
实际应用:通过@Conditional注解,匹配classpath下是否有JdbcTemplate,如果有,则启用MyService实例
@Conditional(MyCondition.class)
@Service
public MyService service() {
xxx
}
常用的@Conditional注解:
springboot默认提供很多类似的条件,这些默认的Condition条件,构成了springboot自动装配的基础。
- @ConfigurationProperties注解:强大的注解,不多说,直接上示例代码
你一定对这样的示例很属性:
准备一个配置文件:db.properties
jdbc.mysql.driver=com.mysql.jdbc.cj.Driver
jdbc.mysql.url=jdbc:mysql://127.0.0.1:3306/content
jdbc.mysql.username=root
jdbc.mysql.passwd=root
使用配置为文件属性:@Value注解
// 配置数据源
@Configuration
public class DataSourceConfiguration {
@Value(jdbc.mysql.url)
public String url;
@Value(jdbc.mysql.username)
public String user;
@Value(jdbc.mysql.password)
public String password;
@Bean
public DruidDataSource dataSource() {
DataSource dataSource = new DruidDataSource();
dataSource.setJdbcUrl(url);
dataSource.setUsername(user);
dataSource.setPassword(password);
return dataSource;
}
}
上面配置的方式,初步看没有什么问题。那我们要是需要共用配置,如何优雅处理呢?看下面改进的例子
通过@ConfigurationProperties改进案例:
// 抽象配置类bean
@Component
@ConfigurationProperties(value="jdbc.mysql")
@Data
pulic class JdbcConfig {
public String url;
public String username;
public String password;
}
// 定义数据源bean
@Configuration
public class DataSourceConfiguration {
@AutoWired
public JdbcConfig config;
@Bean
public DruidDataSource dataSource() {
DataSource dataSource = new DruidDataSource();
dataSource.setJdbcUrl(config.getUrl());
dataSource.setUsername(config.getUser());
dataSource.setPassword(config.getPassword());
return dataSource;
}
}
以上就是spring框架基础核心之一:JavaConfig 相关内容。它主要帮助我们在实际项目中解决配置模块化,清晰化,灵活性与扩展能力。