本文根據嗶哩嗶哩課程內容結合自己自學所得,用于自己復習,如有錯誤歡迎指正;
我在想用一句話激勵我自己努力學習,卻想不出來什么驚為天人、精妙絕倫的句子,腦子里全是上課老師想說卻沒想起的四個字? “ 唯手熟爾 ”,是啊!不過唯手熟爾!
目錄
Spring注解式開發
自定義注解
自定義注解的使用
通過反射機制讀取類上的注解
需求,給你一個包名,包中有很多對象,然后將該包下實現了@component注解的類存到一個map集合中,其中注解ID為key,實例化后的對象為value值;
Spring聲明Bean注解
Spring注解使用
選擇實例化Bean
負責注入的注解
@value注解
@autowired注解
使用@autowired注解的方式解決注入非簡單類型的數據,默認是根據類型裝配的;注意點有下面兩點:
如何解決上面的問題
@Resource注解
@Resource VS @autowired
spring.xml也變成注解類
Spring注解式開發
首先回顧注解相關知識點,
-
什么是注解?
-
注解的定義格式?
-
注解屬性值的定義?
-
如何使用注解?
自定義注解
自定義注解的使用
通過反射機制讀取類上的注解
需求,給你一個包名,包中有很多對象,然后將該包下實現了@component注解的類存到一個map集合中,其中注解ID為key,實例化后的對象為value值;
Spring聲明Bean注解
這里插入一個知識點,其實注解就是元數據,第一次接觸元數據是在JDBC中,所謂元注解就是修飾數據的數據,這里的注解和xml配置信息也是元注解,他們都是為了修飾數據;
在Spring中聲明容器管理的Bean的注解有四個,
-
@component
-
@service
-
@controller
-
@repository
其中只有component注解為原始注解,但是為了提高可讀性,又給他起了下面三個別名;源碼如下:
?@Target(value = {ElementType.TYPE})//target是為了指定注解能夠出現的地方;@Retention(value = RetentionPolicy.RUNTIME)public @interface Component {String value();}?@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Controller {@AliasFor(annotation = Component.class)String value() default "";}??@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Service {@AliasFor(annotation = Component.class)String value() default "";}?@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Repository {@AliasFor(annotation = Component.class)String value() default "";}
Spring注解使用
使用注解的前期步驟:
-
加入aop依賴(引入Spring-context即可,它里面包含了Spring-aop)
-
在配置文件中添加context命名空間
?<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">?</beans>
-
在配置文件中指定掃描的包
<context:component-scan base-package="com.powernode.spring6.bean"/>//如果出現多個包的情況,可以聲明他們的共同父類,或者通過逗號的方式,同時聲明多個包
-
在Bean類上使用注解
?在Bean類上使用注解的幾個小細節;1,在注解的使用中,如果添加的是value屬性,其中value可以省略,只需要寫對應的值即可;2,如果我們在使用注解時,不指定value屬性的值時,Spring會給我自動創建一個屬性值(采用默認方式),即Bean類的名字首字母小寫
選擇實例化Bean
有時候我們有這樣的需求,將某個包下添加了@component注解的Bean單獨實例化,其他的Bean都不實例化,如何解決;
Spring為我們提供了兩種方式,use-default-filter屬性值為false或者true
?<context:component-scan base-package="com.powernode.spring6.bean3" use-default-filters="false"><context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/></context:component-scan>
添加use-default-filter屬性,true時表示采用Spring默認規則,實例化被四個注解標注的Bean;
false表示,不在使用默認的實例化規則,全部都不實例化,如果想要實例化某個注解,就需要配置子標簽context:include-filter,并在其中聲明需要實例化的注解;
負責注入的注解
前面說了實例化Bean的注解@component,現在說替代set注入或者構造函數注入的注解;
@value注解
對于簡單類型,都可以使用value注解,但是這種注解目前是硬編碼;耦合度太高,我也不知道后面會咋弄;直接在添加了@component注解的類屬性上添加@value注解;
@Componentpublic class User {@Value(value = "zhangsan")private String name;@Value("20")private int age;}}
這種注入方式不依賴get\set方法,而且@value注解可以放在屬性上、set方法上、構造方法上、或者構造方法的形參上;
@autowired注解
對于簡單類型我們使用@value注解,那么對于復雜類型我們就使用@autowired注解;這種方式是自動裝配,在之前我們接觸過基于xml文件的自動裝配,他是通過給Bean標簽中添加autowire屬性開啟自動裝配功能,然后他的屬性值就會開始自動裝配,底層調用的是set方法,是通過方法名來自動裝配的,演示案例:
-
? ?
?<bean id="userService" class="com.powernode.spring6.service.UserService" autowire="byName"/><bean id="aaa" class="com.powernode.spring6.dao.UserDao"/>public class UserService {// 這里沒修改private UserDao aaa;?/*public void setAaa(UserDao aaa) {this.aaa = aaa;}*/?// set方法名變化了,就無法自動裝配了public void setDao(UserDao aaa){this.aaa = aaa;}?public void save(){aaa.insert();}}
使用autowire屬性為byName這種自動裝配時必須注意set方法名,還有一種是根據類型自動裝配,但是此時需要注意的是符合條件的實現類必須只有一個;
-
無論是byName還是byType,在裝配的時候都是基于set方法的。而采用注解方式時就不依賴set方法了;
使用@autowired注解的方式解決注入非簡單類型的數據,默認是根據類型裝配的;注意點有下面兩點:
-
第一處:該注解可以標注在哪里?
-
-
構造方法上
-
方法上
-
形參上
-
屬性上
-
注解上
-
-
-
<span style="color:red">第二處:該注解有一個required屬性,默認值是true,表示在注入的時候要求被注入的Bean必須是存在的,如果不存在則報錯。如果required屬性設置為false,表示注入的Bean存在或者不存在都沒關系,存在的話就注入,不存在的話,也不報錯。</span>
由于@autowired注解采用的是默認的方式也就是byType類型,所以實習類必須只有一個,否則會報錯;
如何解決上面的問題
配合@Qualifier注解同時使用,在@Qualifier注解中指明Bean標簽的名稱即可;
? ?@Autowired@Qualifier("userDaoForOracle") // 這個是bean的名字。public void setUserDao(UserDao userDao) {this.userDao = userDao;}
總結:
-
@Autowired注解可以出現在:屬性上、構造方法上、構造方法的參數上、setter方法上。
-
當帶參數的構造方法只有一個,@Autowired注解可以省略。多個的話就會報錯
-
@Autowired注解默認根據類型注入。如果要根據名稱注入的話,需要配合@Qualifier注解一起使用。
@Resource注解
這個注解使用的最廣泛,最受歡迎,同樣他的作用也是完成非簡單類型的注入,
@Resource VS @autowired
@Resource注解也可以完成非簡單類型注入。那它和@Autowired注解有什么區別?
-
@Resource注解是JDK擴展包中的,也就是說屬于JDK的一部分。所以該注解是標準注解,更加具有通用性。(JSR-250標準中制定的注解類型。JSR是Java規范提案。)
-
@Autowired注解是Spring框架自己的。
-
@Resource注解默認根據名稱裝配byName,未指定name時,使用屬性名作為name。通過name找不到的話會自動啟動通過類型byType裝配。
-
@Autowired注解默認根據類型裝配byType,如果想根據名稱裝配,需要配合@Qualifier注解一起用。
-
@Resource注解用在屬性上、setter方法上。
-
@Autowired注解用在屬性上、setter方法上、構造方法上、構造方法參數上。
@Resource注解屬于JDK擴展包,所以不在JDK當中,需要額外引入以下依賴:【如果是JDK8的話不需要額外引入依賴。高于JDK11或低于JDK8需要引入以下依賴。】
<dependency><groupId>jakarta.annotation</groupId><artifactId>jakarta.annotation-api</artifactId><version>2.1.1</version></dependency>
spring.xml也變成注解類
所謂的全注解開發就是不再使用spring配置文件了。寫一個配置類來代替配置文件。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.powernode.spring6.dao,com.powernode.spring6.service"/></beans>
二者比較
?@Configuration@ComponentScan({"com.powernode.spring6.dao", "com.powernode.spring6.service"})public class Spring6Configuration {}
但是相應的測試程序就需要改變了:
?@Testpublic void testNoXml(){ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Spring6Configuration.class);UserService userService = applicationContext.getBean("userService", UserService.class);userService.save();}
ClassPathXmlApplicationContext?
類換成了?AnnotationConfigApplicationContext
他日若遂凌云志,敢笑黃巢不丈夫,加油!!!