關(guān)于@Component和@Bean使用注意
@Component和@Bean使用注意
大家都知道@Component和@Bean是spring生成bean對(duì)象的注解,@Component只可以加在類上,如果該類在spring的掃描路徑之下就可以生成bean對(duì)象,@Bean一般與@Configuration結(jié)合使用,指定方法名為bean對(duì)象的名稱,返回對(duì)象為bean對(duì)象。
正常情況的使用大家肯定都沒有問題,下面列舉幾種需要注意的情況:
項(xiàng)目結(jié)構(gòu)
1、兩個(gè)相同名稱的類在不同包下加@Component
@Component public class Bean { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Bean{" + "name='" + name + '\'' + '}'; } }
兩個(gè)Bean類代碼如上,啟動(dòng)項(xiàng)目會(huì)報(bào)錯(cuò)
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.example.demo.DemoApplication]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'bean' for bean class [com.example.demo.b.Bean] conflicts with existing, non-compatible bean definition of same name and class [com.example.demo.a.Bean]
解決方式:
修改其中一個(gè)類的名稱,或者在@Component中指定不一樣的bean的名稱。
2、存在同名的@Bean方法名和@Component類
@Configuration @ComponentScan("com.example.demo") public class BeanConfig { @Bean com.example.demo.a.Bean bean(){ com.example.demo.a.Bean bean = new com.example.demo.a.Bean(); bean.setName("A"); return bean; } }
以spring的方式啟動(dòng)
//@SpringBootApplication public class DemoApplication { @Autowired ApplicationContext ioc; public static void main(String[] args) { // SpringApplication.run(DemoApplication.class, args); AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class); Object bean = applicationContext.getBean("bean"); System.out.println(bean); } }
結(jié)果如下:
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean'
Bean{name='A'}
可以看出@Bean會(huì)覆蓋@Component結(jié)果。
以springboot方式啟動(dòng)
結(jié)果如下:
***************************
APPLICATION FAILED TO START
***************************Description:
The bean 'bean', defined in class path resource [com/example/demo/config/BeanConfig.class], could not be registered. A bean with that name has already been defined in file [D:\learn-master\demo\target\classes\com\example\demo\b\Bean.class] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
根據(jù)提示可以看出需要在配置文件增加spring.main.allow-bean-definition-overriding=true
3、如果存在多個(gè)@Bean方法名相同重載
@Configuration @ComponentScan("com.example.demo") public class BeanConfig { @Bean com.example.demo.a.Bean bean(){ com.example.demo.a.Bean bean = new com.example.demo.a.Bean(); bean.setName("A"); return bean; } @Bean com.example.demo.a.Bean bean(com.example.demo.a.Bean bean1, com.example.demo.a.Bean bean2){ com.example.demo.a.Bean bean = new com.example.demo.a.Bean(); bean.setName("B"); return bean; } @Bean com.example.demo.a.Bean bean(com.example.demo.a.Bean bean1){ com.example.demo.a.Bean bean = new com.example.demo.a.Bean(); bean.setName("C"); return bean; } }
雖然有三個(gè)個(gè)@Bean,但是肯定只會(huì)生成一個(gè)bean的Bean,那么Spring在處理@Bean時(shí),也只會(huì)生成一個(gè)bean的BeanDefinition,比如Spring先解析到第一個(gè)@Bean,會(huì)生成一個(gè)BeanDefinition,此時(shí)isFactoryMethodUnique為true,但是解析到第二個(gè)@Bean時(shí),會(huì)判斷出來beanDefinitionMap中已經(jīng)存在一個(gè)bean的BeanDefinition了,那么會(huì)把之前的這個(gè)BeanDefinition的isFactoryMethodUnique修改為false,并且不會(huì)生成新的BeanDefinition了。
并且后續(xù)在根據(jù)BeanDefinition創(chuàng)建Bean時(shí),會(huì)根據(jù)isFactoryMethodUnique來操作,如果為true,那就表示當(dāng)前BeanDefinition只對(duì)應(yīng)了一個(gè)方法,那也就是只能用這個(gè)方法來創(chuàng)建Bean了,但是如果isFactoryMethodUnique為false,那就表示當(dāng)前BeanDefition對(duì)應(yīng)了多個(gè)方法,用推斷構(gòu)造方法的邏輯,去選擇用哪個(gè)方法來創(chuàng)建Bean。
其屬性會(huì)將spring的bean自動(dòng)注入。
這個(gè)操作是不會(huì)報(bào)錯(cuò)的。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用Java8實(shí)現(xiàn)觀察者模式的方法(上)
本文給大家介紹使用java8實(shí)現(xiàn)觀察者模式的方法,涉及到j(luò)ava8觀察者模式相關(guān)知識(shí),對(duì)此感興趣的朋友一起學(xué)習(xí)吧2016-02-02Spring @Primary作用和實(shí)現(xiàn)原理詳解
今天分享一下Spring中的@Primary注解,Primary的意思是主要的,我們?cè)谑褂胹pring的時(shí)候,難免會(huì)定義多個(gè)類型相同的bean,這時(shí)候如果不采取一些方法,那么是無法正常使用bean的,所以本就給大家介紹Spring @Primary的作用和實(shí)現(xiàn)原理2023-07-07Java設(shè)計(jì)模式編程之解釋器模式的簡(jiǎn)單講解
這篇文章主要介紹了Java設(shè)計(jì)模式編程之解釋器模式的講解,解釋器設(shè)計(jì)模式要注意其引發(fā)的性能問題,需要的朋友可以參考下2016-04-04Java?HttpURLConnection使用方法與實(shí)例演示分析
這篇文章主要介紹了Java?HttpURLConnection使用方法與實(shí)例演示,HttpURLConnection一個(gè)抽象類是標(biāo)準(zhǔn)的JAVA接口,該類位于java.net包中,它提供了基本的URL請(qǐng)求,響應(yīng)等功能,下面我們來深入看看2023-10-10淺談Java中幾種常見的比較器的實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄獪\談Java中幾種常見的比較器的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10