在Springboot項(xiàng)目中我們可以通過main方法啟動(dòng)項(xiàng)目,在需要啟動(dòng)的主類中我們需要加入@SpringBootApplication這個(gè)注解,告訴spring boot,這個(gè)是程序的入口。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
不加這個(gè)注解是無法啟動(dòng)項(xiàng)目的,下面查看下SpringBootApplication,本質(zhì)是一個(gè)接口,源碼如下:
@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 {
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
@AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude")
Class<?>[] exclude() default {};
//根據(jù)class來排除特定的類加入spring容器,傳入?yún)?shù)value類型是class類型
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
/
@AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName")
String[] excludeName() default {};
//根據(jù)class name來排除特定的類加入spring容器,傳入?yún)?shù)value類型是class的全類名字符串?dāng)?shù)組
/*
* Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
* for a type-safe alternative to String-based package names.
* @return base packages to scan
* @since 1.3.0
/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
//指定掃描包,參數(shù)是包名的字符串?dāng)?shù)組
/*
* Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
* scan for annotated components. The package of each class specified will be scanned.
* <p>
* Consider creating a special no-op marker class or interface in each package that
* serves no purpose other than being referenced by this attribute.
* @return base packages to scan
* @since 1.3.0
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
//掃描特定的包,參數(shù)類似是Class類型數(shù)組
}
在這個(gè)類上有三個(gè)注解:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
我們可以用這三個(gè)注解代替@SpringBootApplication:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
其中
@SpringBootConfiguration:繼承自@Configuration,表示SpringBoot的配置注解,功能一致,標(biāo)注當(dāng)前的類為配置類,并將當(dāng)前類內(nèi)聲明的一個(gè)或多個(gè)@Bean注解標(biāo)記的方法實(shí)例納入到Spring容器中,并且實(shí)例名就是方法名。@EnableAutoConfiguration:表示自動(dòng)配置,作用是啟動(dòng)自動(dòng)的配置,意思就是Springboot根據(jù)你添加的jar包來配置你的項(xiàng)目的默認(rèn)配置,比如根據(jù)spring-boot-starter-web,來判斷你的項(xiàng)目是否需要添加webmvc和tomcat,就會(huì)自動(dòng)幫你配置web項(xiàng)目中所需要的默認(rèn)配置。
@ComponentScan:表示SpringBoot掃描Bean的規(guī)則,比如掃面哪些包,掃描當(dāng)前包及其子包下被@Component,@Controller,@Service,@Repository注解標(biāo)記的類并納入到spring容器中進(jìn)行管理。是以前的<context:component-scan>
@Configuration:加了這個(gè)注解的類被認(rèn)為是SpringBoot的配置類,我們知道可以在application.yml/properties設(shè)置一些配置,也可以通過代碼設(shè)置配置。
如果我們要通過代碼設(shè)置配置,就必須在這個(gè)類上加這個(gè)注解,通俗的講,@Configuration一般與@Bean(注釋是用來表示一個(gè)方法實(shí)例化,配置和初始化是由 Spring IoC 容器管理的一個(gè)新的對(duì)象)注解配合使用,用@Configuration注解類等價(jià)于XML中配置beans,用@Bean注解方法等價(jià)與XML中配置bean:
<beans>
<bean id = "userService" class="com.user.UserService">
<property name="userDAO" ref = "userDAO">
</property>
</bean>
<bean id = "userDAO" class="com.user.UserDAO">
</bean>
</beans>
——>等價(jià)于:
package org.spring.com.user;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Config {
@Bean public UserService getUserService(){
UserService userService = new UserService();
userService.setUserDAO(null);
return userService;
}
@Bean public UserDAO getUserDAO(){
return new UserDAO();
}
}
package org.spring.com.user;
public class UserService {
private UserDAO userDAO;
public UserDAO getUserDAO() {
return userDAO;
}
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
}
package org.spring.com.user;
public class UserDAO {
}
@Configuration
public class WebConfig extends WebMvcConfigurationSupport{
@Override
protected void addInterceptors(InterceptorRegistry registry) {
super.addInterceptors(registry);
registry.addInterceptor(new ApiInterceptor());
}
}
不過,Springboot官方推薦使用SpringBootConfiguration來代替Configuration
@Bean是方法級(jí)別上的注解,主要添加在@Configuration或者@SpringBootConfiguration注解的類,有時(shí)也可以添加在@Component注解的類,作用是定義一個(gè)bean
注意:使用@ComponentScan注解代替@SpringBootApplication注解,也可以正常運(yùn)行程序。原因是@SpringBootApplication中包含@ComponentScan,并且springboot會(huì)將入口類看作是一個(gè)@SpringBootConfiguration標(biāo)記的配置類,所以定義在入口類Application中的Runnable也可以納入到容器管理。
SpringBootApplication執(zhí)行流程圖如下:

番外:@Autowired與@Resource:
@Resource的作用相當(dāng)于@Autowired,只不過@Autowired按byType自動(dòng)注入,而@Resource默認(rèn)按 byName自動(dòng)注入罷了。@Resource有兩個(gè)屬性是比較重要的,分是name和type,Spring將@Resource注解的name屬性解析為bean的名字,而type屬性則解析為bean的類型。所以如果使用name屬性,則使用byName的自動(dòng)注入策略,而使用type屬性時(shí)則使用byType自動(dòng)注入策略。如果既不指定name也不指定type屬性,這時(shí)將通過反射機(jī)制使用byName自動(dòng)注入策略。
1.@Autowired與@Resource都可以用來裝配bean. 都可以寫在字段上,或?qū)懺趕etter方法上。
@Autowired默認(rèn)按類型裝配(這個(gè)注解是屬業(yè)spring的),默認(rèn)情況下必須要求依賴對(duì)象必須存在,如果要允許null值,可以設(shè)置它的required屬性為false,如:@Autowired(required=false) ,如果我們想使用名稱裝配可以結(jié)合@Qualifier注解進(jìn)行使用,如下:
@Autowired()@Qualifier("baseDao")
privateBaseDao baseDao;
@Resource(這個(gè)注解屬于J2EE的),默認(rèn)按照名稱進(jìn)行裝配,名稱可以通過name屬性進(jìn)行指定,如果沒有指定name屬性,當(dāng)注解寫在字段上時(shí),默認(rèn)取字段名進(jìn)行安裝名稱查找,如果注解寫在setter方法上默認(rèn)取屬性名進(jìn)行裝配。當(dāng)找不到與名稱匹配的bean時(shí)才按照類型進(jìn)行裝配。但是需要注意的是,如果name屬性一旦指定,就只會(huì)按照名稱進(jìn)行裝配。
@Resource(name="baseDao")
privateBaseDao baseDao;
推薦使用:@Resource注解在字段上,這樣就不用寫setter方法了,并且這個(gè)注解是屬于J2EE的,減少了與spring的耦合。這樣代碼看起就比較優(yōu)雅。
@Autowired//默認(rèn)按type注入
@Qualifier("cusInfoService")//一般作為@Autowired()的修飾用
@Resource(name="cusInfoService")//默認(rèn)按name注入,可以通過name和type屬性進(jìn)行選擇性注入
一般@Autowired和@Qualifier一起用,@Resource單獨(dú)用。
當(dāng)然沒有沖突的話@Autowired也可以單獨(dú)用
其他常用注解:
--定義Bean的注解
@Controller
@Controller("Bean的名稱")
定義控制層Bean,如Action
@Service
@Service("Bean的名稱")
定義業(yè)務(wù)層Bean
@Repository
@Repository("Bean的名稱")
定義DAO層Bean
@Component
定義Bean, 不好歸類時(shí)使用.
--自動(dòng)裝配Bean (選用一種注解就可以)
@Autowired (Srping提供的)
默認(rèn)按類型匹配,自動(dòng)裝配(Srping提供的),可以寫在成員屬性上,或?qū)懺趕etter方法上
@Autowired(required=true)
一定要找到匹配的Bean,否則拋異常。 默認(rèn)值就是true
@Autowired
@Qualifier("bean的名字")
按名稱裝配Bean,與@Autowired組合使用,解決按類型匹配找到多個(gè)Bean問題。
@Resource JSR-250提供的
默認(rèn)按名稱裝配,當(dāng)找不到名稱匹配的bean再按類型裝配.
可以寫在成員屬性上,或?qū)懺趕etter方法上
可以通過@Resource(name="beanName") 指定被注入的bean的名稱, 要是未指定name屬性, 默認(rèn)使用成員屬性的變量名,一般不用寫name屬性.
@Resource(name="beanName")指定了name屬性,按名稱注入但沒找到bean, 就不會(huì)再按類型裝配了.
@Inject 是JSR-330提供的
按類型裝配,功能比@Autowired少,沒有使用的必要。
--定義Bean的作用域和生命過程
@Scope("prototype")
值有:singleton,prototype,session,request,session,globalSession
@PostConstruct
相當(dāng)于init-method,使用在方法上,當(dāng)Bean初始化時(shí)執(zhí)行。
@PreDestroy
相當(dāng)于destory-method,使用在方法上,當(dāng)Bean銷毀時(shí)執(zhí)行。
--聲明式事務(wù)
@Transactional
@Autowired @Resource @Qualifier的區(qū)別
實(shí)用理解:@Autowired @Resource 二選其一,看中哪個(gè)就用哪個(gè)。
簡(jiǎn)單理解:
@Autowired 根據(jù)類型注入,
@Resource 默認(rèn)根據(jù)名字注入,其次按照類型搜索
@Autowired @Qualifie("userService") 兩個(gè)結(jié)合起來可以根據(jù)名字和類型注入
復(fù)雜理解:
比如你有這么一個(gè)Bean
@Service(“UserService”)
public Class UserServiceImpl implements UserService{};
現(xiàn)在你想在UserController 里面使用這個(gè)UserServiceImpl
public Class UserController {
@AutoWire //當(dāng)使用這個(gè)注入的時(shí)候上面的 UserServiceImpl 只需要這樣寫 @Service,這樣就會(huì)自動(dòng)找到UserService這個(gè)類型以及他的子類型。UserServiceImpl 實(shí)現(xiàn)了UserService,所以能夠找到它。不過這樣有一個(gè)缺點(diǎn),就是當(dāng)UserService實(shí)現(xiàn)類有兩個(gè)以上的時(shí)候,這個(gè)時(shí)候會(huì)找哪一個(gè)呢,這就造成了沖突,所以要用@AutoWire注入的時(shí)候要確保UserService只有一個(gè)實(shí)現(xiàn)類。
@Resource 默認(rèn)情況下是按照名稱進(jìn)行匹配,如果沒有找到相同名稱的Bean,則會(huì)按照類型進(jìn)行匹配,有人可能會(huì)想了,這下好了,用這個(gè)是萬能的了,不用管名字了,也不用管類型了,但這里還是有缺點(diǎn)。首先,根據(jù)這個(gè)注解的匹配效果可以看出,它進(jìn)行了兩次匹配,也就是說,如果你在UserService這個(gè)類上面這樣寫注解,@Service,它會(huì)怎么找呢,首先是找相同名字的,如果沒有找到,再找相同類型的,而這里的@Service沒有寫名字,這個(gè)時(shí)候就進(jìn)行了兩次搜索,顯然,速度就下降了許多。也許你還會(huì)問,這里的@Service本來就沒有名字,肯定是直接進(jìn)行類型搜索啊。其實(shí)不是這樣的,UserServiceImpl 上面如果有@Service默認(rèn)的名字 是這個(gè)userServiceImpl,注意看,就是把類名前面的大寫變成小寫,就是默認(rèn)的Bean的名字了。 @Resource根據(jù)名字搜索是這樣寫@Resource("userService"),如果你寫了這個(gè)名字叫userService,那么UserServiceImpl上面必須也是這個(gè)名字,不然還是會(huì)報(bào)錯(cuò)。
@Autowired @Qualifie("userService") 是直接按照名字進(jìn)行搜索,也就是說,對(duì)于UserServiceImpl 上面@Service注解必須寫名字,不寫就會(huì)報(bào)錯(cuò),而且名字必須是@Autowired @Qualifie("userService") 保持一致。如果@Service上面寫了名字,而@Autowired @Qualifie() ,一樣會(huì)報(bào)錯(cuò)。
private UserService userService;
}
說了這么多,可能你有些說暈了,那么怎么用這三個(gè)呢,要實(shí)際的工作是根據(jù)實(shí)際情況來使用的,通常使用AutoWire和@Resource多一些,bean的名字不用寫,而UserServiceImpl上面能會(huì)這樣寫 @Service("userService")。這里的實(shí)際工作情況,到底是什么情況呢?說白了就是整個(gè)項(xiàng)目設(shè)計(jì)時(shí)候考慮的情況,如果你的架構(gòu)設(shè)計(jì)師考慮的比較精細(xì),要求比較嚴(yán)格,要求項(xiàng)目上線后的訪問速度比較好,通常是考慮速度了。這個(gè)時(shí)候@AutoWire沒有@Resource好用,因?yàn)锧Resource可以根據(jù)名字來搜索,是這樣寫的@Resource("userService")。這個(gè)@Autowired @Qualifie("userService") 也可以用名字啊,為什么不用呢,原因很簡(jiǎn)單,這個(gè)有點(diǎn)長(zhǎng),不喜歡,增加工作量。因?yàn)楦鶕?jù)名字搜索是最快的,就好像查數(shù)據(jù)庫一樣,根據(jù)Id查找最快。因?yàn)檫@里的名字與數(shù)據(jù)庫里面的ID是一樣的作用。這個(gè)時(shí)候,就要求你多寫幾個(gè)名字,工作量自然就增加了。而如果你不用注解,用xml文件的時(shí)候,對(duì)于注入Bean的時(shí)候要求寫一個(gè)Id,xml文件時(shí)候的id就相當(dāng)于這里的名字。
說了那么多沒用,你能做的就是簡(jiǎn)單直接,什么最方便就用什么,
你就直接用@Resource得了,如果你喜歡用@AutoWired也行,不用寫名字
例子:
@Resource使用注意事項(xiàng)
例:
@Resource
CityDao citydao;
【1】 則首先根據(jù)類名,將類名首字母小寫得到cityDao,然后去Spring的配置文件中尋找id為cityDao的bean,即進(jìn)行名稱匹配
【2】若Spring的配置文件中沒有id為cityDao的bean,則再根據(jù)類型進(jìn)行匹配,在配置文件中尋找class為CityDao的bean
@Autowired使用注意事項(xiàng)
例:
@Autowired
CityDao cityDao;
【1】直接根據(jù)類型進(jìn)行匹配,Spring會(huì)去配置文件中尋找class為CityDao的bean
@Qualifer使用注意事項(xiàng)
例:
@Autowired
@Qualifer("cityDao2")
CityDao cityDao;
【1】@Qualifer不能單獨(dú)使用,否則會(huì)出現(xiàn)空指針錯(cuò)誤
【2】需要配合@Autowired使用,會(huì)從Spring配置文件中尋找id為cityDao2的bean,即進(jìn)行名稱匹配