寫了兩年代碼之后再來談一談Spring中的Bean
(一)什么是Bean
Spring中的Bean簡單來講就是一個個被Spring容器管理的Java對象,我們寫了一個類之后,這個類只是一個單純的Java類,可以通過new的方式去創(chuàng)建它。當我們把這個類添加到Spring的容器里之后,這個類就變成了Bean,由Spring容器管理,可以通過自動注入的方式去使用。
(二)如何往Spring容器中添加Bean
這里列出四種常用的添加Bean的方式。
1、@Bean: 寫一個普通的類時最常用的添加Bean的方式
2、@ComponentScan + @Controller @Service @Component @Repository:SpringBoot寫多了之后一定會很熟悉這些。
3、@Import:通過導入的方式注入Bean
4、@ImportBeanDefinitionRegister:和Import類似,可以指定Bean的名稱
(三)Bean的作用域
首先介紹最基本的@Bean注解,@Bean注解聲明這個類是一個Bean,在Spring5之前,大部分的聲明都會放到配置文件里,Spring5之后通過兩個注解就可以完成。以Teacher類為例
public class Teacher {
}
@Configuration
public class MainConfig {
@Bean
public Teacher teacher(){
return new Teacher();
}
}
在不指定@Scope的情況下,所有bean的實例都是單實例的bean,并且是餓漢式加載(容器啟動時就創(chuàng)建好了)??梢酝ㄟ^注解@Lazy實現(xiàn)懶加載(在調用時被加載)。
@Bean
//@Lazy
public User user(){
return new User();
}
指定@Scope為prototype表示為多實例,并且是懶漢式加載(使用時才會創(chuàng)建)
@Bean
@Scope(value = "prototype")
public User user(){
return new User();
}
列出其他的幾種Bean作用域:
singleton 單例(默認) prototype 多實例 request 同一次請求 session 同一個會話級別
(四)Bean的常用注解
有幾個注解經(jīng)常會和@Bean一起使用
4.1 Conditional
Conditional注解的意思是條件,即滿足條件的情況下才會生效
比如我在Bean中配置了Conditional:
@Bean
@Conditional(value = TeacherCondition.class)
public Teacher teacher(){
return new Teacher();
}
TeacherCondition 代碼如下:如果Spring的Bean中有名字為student的,則返回true,否則返回false
public class TeacherCondition implements Condition {
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
if (conditionContext.getBeanFactory().containsBean("student")){
return true;
}
return false;
}
}
最后的結果就是,如果TeacherCondition返回的是true,則teacher這個bean會被注冊到容器中,否則就不會注冊到容器中。
4.2 ComponentScan
這個注解會和Controller、Service等同時出現(xiàn),給一個類添加Controller、Service等注解后,需要在配置類中增加ComponentScan,ComponentScan掃描到的包下的Controller、Service等注解才會生效:
@Configuration
//最基本的掃描路徑方式
//@ComponentScan(basePackages = {"com.javayz.testcompentscan"})
//增加了Filter的方式
@ComponentScan(basePackages = {"com.javayz.testcompentscan"},includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class, Service.class}),
@ComponentScan.Filter(type = FilterType.CUSTOM,value = {TestFilterType.class})
},useDefaultFilters = false)
public class MainConfig {
@Bean
@Scope(value = "prototype")
public User user(){
return new User();
}
}
Filter是在掃描時的過濾器,比如設置FilterType.ANNOTATION表示只有這里設置的注解才會被掃描到,F(xiàn)ilterType.CUSTOM是自定義過濾器,TestFilterType 類進行了一層判斷:包名為dao下的類會被注冊到Bean容器中
public class TestFilterType implements TypeFilter {
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//獲取當前類的class源信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
if (classMetadata.getClassName().contains("dao")){
return true;
}
return false;
}
}
4.3 @Import
@Import可以用來往容器中導入第三方的組件,也可以起到和@Bean一樣的作用:
@Configuration
//@Import(value = {Teacher.class, Student.class})
//@Import(value = {MyImportSelector.class})
@Import(value = {MyBeanDefinitionRegister.class})
public class MainConfig {
}
第一種方式直接導入對應的類,這里和直接寫@Bean效果一致
@Import(value = {Teacher.class, Student.class})
第二種方式導入ImportSelector對象,通過selectImports方法返回要導入Bean的全限定名:
public class MyImportSelector implements ImportSelector {
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{"com.javayz.testimport.compent.Teacher"};
}
}
第三種方式通過BeanDefinitionRegister注入Bean(可以指定Bean的名稱)
public class MyBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Student.class);
registry.registerBeanDefinition("student",rootBeanDefinition);
}
}
Import注解最常用的場景就是SpringBoot自動注入,在SpringBoot自動注入源碼中導出可以看到@Import注解的身影。
(五)Bean的初始化和銷毀
當由容器管理Bean的生命周期時,我們可以通過自己指定Bean方法的初始化方法和銷毀方法,使得一個Bean在初始化和銷毀時能執(zhí)行自己的方法。
1、自定義初始化方法和銷毀方法
public class Teacher {
public Teacher(){
System.out.println("Teacher 構造方法");
}
public void init(){
System.out.println("Teacher 初始化方法");
}
public void destory(){
System.out.println("Teacher 銷毀方法");
}
}
@Configuration
public class MainConfig {
@Bean(initMethod = "init",destroyMethod = "destory")
public Teacher teacher(){
return new Teacher();
}
}
對于單例bean(singleton)容器啟動的時候,bean對象就創(chuàng)建了,在容器銷毀的時候,就會去調用Bean的銷毀方法。
對于多實例的bean,容器啟動的時候bean還未被創(chuàng)建,在獲取Bean的時候才會被創(chuàng)建,并且bean的銷毀不受IOC容器的管理。
2、通過 InitializingBean, DisposableBean 接口實現(xiàn)
Spring的這兩個接口也可以實現(xiàn)初始化和銷毀的功能。
public class Student implements InitializingBean, DisposableBean {
public Student(){
System.out.println("Student 構造方法");
}
@Override
public void destroy() throws Exception {
System.out.println("Student銷毀");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Student初始化");
}
}
@Configuration
public class MainConfig {
@Bean
public Student student(){
return new Student();
}
}
3、BeanPostProcessor
BeanPostProcessor在所有Bean的初始化前和初始化后都會被調用
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean初始化前");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean初始化后");
return bean;
}
}
@ComponentScan
@Configuration
public class MainConfig {
@Bean(initMethod = "init",destroyMethod = "destory")
public Teacher teacher(){
return new Teacher();
}
@Bean
public Student student(){
return new Student();
}
}
(六)總結
別看Bean這個概念聽起來簡單,里面的內容還真不少。Spring的核心之一IOC也就是對Bean進行管理。我是魚仔,我們下期再見!
到此這篇關于寫了兩年代碼之后再來看看Spring中的Bean的文章就介紹到這了,更多相關Spring中的Bean內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
javaweb用戶注銷后點擊瀏覽器返回刷新頁面重復登錄問題的解決方法
這篇文章主要為大家詳細介紹了javaweb用戶注銷后點擊瀏覽器返回刷新頁面重復登錄問題的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-09-09
SWT(JFace) Wizard(Eclipse插件編程必備)
SWT(JFace)小制作:Wizard(Eclipse插件編程必備)2009-06-06
淺談Java(SpringBoot)基于zookeeper的分布式鎖實現(xiàn)
這篇文章主要介紹了Java(SpringBoot)基于zookeeper的分布式鎖實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-03-03
如何使用?Spring?Boot?搭建?WebSocket?服務器實現(xiàn)多客戶端連接
本文介紹如何使用SpringBoot快速搭建WebSocket服務器,實現(xiàn)多客戶端連接和消息廣播,WebSocket協(xié)議提供全雙工通信,SpringBoot通過@ServerEndpoint簡化配置,支持實時消息推送,適用于聊天室或通知系統(tǒng)等應用場景2024-11-11

