JavaConfig与常见Annotation(必知必会系列)
Spring中Bean的生命周期
JavaConfig
说注解之前,我们先了解下JavaConfig。在注解方式实例化Bean之前,我们都是通过XML来配置Bean以及其依赖关系的,造成了项目中有大量的XML文件,使项目变得复杂,不便于维护。所以JavaConfig 就应运而生了,JavaConfig是Spring的一个子项目。它基于Java代码和Annotation注解来描述Bean之间的依赖绑定关系。
例如:teacherService类,通过XML配置如下:
<bean id="teacherService" class="com.jay.spring.configuration.TeacherServiceImpl"></bean>
- 1
通过JavaConfig 配置就是这样的:
@Configuration
public class TeacherConfiguration { @Bean public TeacherService teacherService(){ return new TeacherServiceImpl(); }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
@Configuration
注解标注在类上,相当于把该类作为Spring的XML配置文件中的<beans>
,其作用为:配置Spring容器,需要注意的是:
@Configuration
不可以是final类型;@Configuration
不可以是匿名类- 嵌套的Configuration必须是静态类。
@Bean
注解标注方法上(返回某个实例的方法),等价于Spring的XML配置文件中的<bean>
,作用是注册bean对象,对象实例的名字默认是方法名。我们也可以通过name 属性来指定实例名。 @Bean
注解默认作用域为单例singleton 作用域,可通过@Scope(”prototype“)
设置为原型作用域- 既然@Bean的作用是注册bean对象,那么完全可以使用
@Component
、@Controller
、@Service
、@Ripository
等注解注册bean,当然需要配置@ComponentScan
注解进行自动扫描。
@ComponentScan
@ComponentScan
注解对应Spring的XML配置文件中的<context:component-scan/>
表示启动组件扫描,Spring会自动扫描所有通过注解配置的bean,然后将其注册到IOC容器中,我们可以通过basePackages属性来指定@ComponentScan
自动扫描的范围,如果不指定,则默认从声明@ComponentScan
所在类的package进行扫描,正是因为如此,SpringBoot的启动类都是默认在/src/main/java下。
@Import
@Import
注解用于导入配置类,应用场景就是一个配置类中的一个Bean依赖于另一个配置类中的一个Bean。例如:下面有一个TeacherConfiguration
配置类。这个类里定义了一个TeacherService的实例。
@Configuration
public class TeacherConfiguration { @Bean public TeacherService teacherService(){ return new TeacherServiceImpl(); }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
还有一个StudentConfiguration
配置类,这个配置类中定义的StudentService的实例需要依赖TeacherService对象。所以我们在StudentConfiguration
中将TeacherConfiguration
引入,如下所示:
@Configuration
//可以同时导入多个配置文件,比如:@Import({A.class,B.class})
@Import(TeacherConfiguration.class)
public class StudentConfiguration { @Bean public StudentService studentService(TeacherService teacherService) { return new StudentServiceImpl(teacherService); }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
StudentServiceImpl 类中如下所示:
public class StudentServiceImpl implements StudentService { private TeacherService teacherService; public StudentServiceImpl(TeacherService teacherService) { this.teacherService = teacherService; }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
@Import
注解支持导入普通java类,并将其声明成一个Bean,主要用于将多个分散的JavaConfig配置类融合成一个更大的config类。
@Import
注解在4.2之前只支持导入配置类。- 在4.2之后@Import注解支持导入普通的java类,并将其声明成一个Bean。
@Import
三种使用方式:
- 直接导入普通的Java类。
- 配合自定义的ImportSelector使用。
- 配合ImportBeanDefinitionRegistrar使用。
@Conditional
@Conditional
注解表示满足某种条件之后才开始初始化一个Bean或者启动某些配置,它一般用在由@Component
、@Service
、@Configuration
等注解标识的类上面,或者由@Bean
标记的方法上。如果一个@Configuration
类标记了 @Conditional
,则该类中所有标识了@Bean
的方法和@Import
注解导入的相关类将遵从这些条件。
如果我们需要自定义自己的条件类,所要做的就是实现Condtition接口,并覆盖它的matches()
方法。
下面举栗子说明下,
public class JdbcTemplateCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { try { context.getClassLoader().loadClass("org.springframework.jdbc.core.JdbcTemplate"); return true; } catch (ClassNotFoundException e) { e.printStackTrace(); } return false; }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
当你用Java来声明Bean的时候,可以使用这个自定义条件类:
@Conditional(JdbcTemplateCondition.class)
@Service
public class JdbcDemoService {
}
- 1
- 2
- 3
- 4
- 5
这个栗子中只有当JdbcTemplateCondition类的条件成立时才会创建JdbcDemoService这个Bean,也就是说JdbcDemoService这个Bean的创建条件是classpath里面包括JdbcTemplate,否则这个bean的声明就会被忽略掉。
在SpringBoot中还有一些有意思的条件注解。
@ConfigurationProperties与@EnableConfigurationProperties
当某些属性的值需要配置的时候,我们一般会在applcation.properties
文件中新建配置项,然后通过@Value
注解来获取配置项,比如下面配置数据源的代码。
// jdbc config
jdbc.mysql.url=jdbc:mysql://localhost:3306/category
jdbc.mysql.username=root
jdbc.mysql.password=123456
//配置数据源
@Configuration
public class DataSouceConfiguration { @Value("jdbc.mysql.url") public String url; @Value("jdbc.mysql.username") public String user; @Value("jdbc.mysql.password") public String password; @Bean public DataSource dataSource() { DataSource ds = new BasicDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl(url); ds.setUsername(user); ds.setPassword(password); return ds; }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
如果配置比较多的话,是用@Value
来获取注解就比较low了,代码也不美观。没关系,我们还有个更加好用的注解@ConfigurationProperties
。这个注解可以把同类的配置信息自动封装成实体类,如上获取数据源的代码可以改写成下面这样,由于篇幅的问题这里省略了setter、getter方法,但是实际开发中这个是必须的,否则无法成功注入。
@Configuration
@ConfigurationProperties(prefix = "jdbc.mysql")
public class DataSouceConfiguration2 { public String url; public String user; public String password; @Bean public DataSource dataSource() { DataSource ds = new BasicDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl(url); ds.setUsername(user); ds.setPassword(password); return ds; }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
@EnableConfigurationProperties 注解表示对@ConfigurationProperties的内嵌支持,
默认会将对应Properties Class作为Bean 注入到IOC容器中,即在相应的Properties 类上不用加@Component注解。
组合注解
当可能大量同时使用到几个注解到同一个类上,就可以考虑将这几个注解到别的注解上,被注解的注解我们就称之为组合注解,例如@SpringBootApplication
注解。
- 元注解:可以注解到别的注解上的注解。
- 组合注解:被注解的注解我们就称之为组合注解。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
如上@SpringBootApplication
注解上注解了@SpringBootConfiguration
,@EnableAutoConfiguration
以及@ComponentScan
三个元注解。
总结
本文首先介绍了JavaConfig讲到了注解与Spring的XML配置文件中的节点的配置关系,接着就是介绍了各种常用的注解。希望对读者们有所帮助。
文章来源: feige.blog.csdn.net,作者:码农飞哥,版权归原作者所有,如需转载,请联系作者。
原文链接:feige.blog.csdn.net/article/details/105905395
- 点赞
- 收藏
- 关注作者
评论(0)