最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring6注解式開(kāi)發(fā)示例詳解

 更新時(shí)間:2026年02月06日 08:55:36   作者:NE_STOP  
文章介紹了Spring框架中使用注解進(jìn)行開(kāi)發(fā)的機(jī)制,包括如何定義和使用自定義注解,通過(guò)反射機(jī)制讀取注解,以及如何根據(jù)注解進(jìn)行組件掃描和bean的實(shí)例化,感興趣的朋友跟隨小編一起看看吧

spring框架創(chuàng)建bean就是利用反射機(jī)制

反射機(jī)制的代碼如下:

public static void main(String[] args) throws Exception {
    System.out.println("Hello, World!");
    // 使用反射機(jī)制調(diào)用方法
    // 獲取類(lèi)
    Class<?> clazz = Class.forName("com.ali.bean2.SomeService");
    // 獲取方法
    Method method = clazz.getMethod("doSomething", String.class, int.class);
    // 獲取對(duì)象
    Object obj = clazz.newInstance();
    // 方法調(diào)用
    // obj: 哪個(gè)對(duì)象調(diào)用這個(gè)方法
    // "hello", 42: 方法參數(shù)
    // hello: 方法的返回值
    Object hello = method.invoke(obj, "hello", 42);
}

spring IoC注解式開(kāi)發(fā)

注解主要是為了簡(jiǎn)化xml配置。

注解怎么定義

新建Java Class 時(shí)選擇Annoation 類(lèi)型的文件,這樣就創(chuàng)建了一個(gè)新的注解

// 自定義注解
// @Target 標(biāo)注注解的注解,叫做元注解
// ElementType.TYPE: 表示可以標(biāo)注在類(lèi)上
// ElementType.FIELD: 表示可以標(biāo)注在屬性上
// 使用某個(gè)注解的時(shí)候,如果注解的屬性名是value,可以省略屬性名
// 使用某個(gè)注解的時(shí)候,如果注解的屬性值是數(shù)組,并且數(shù)組中只有一個(gè)值,可以省略大括號(hào)
@Target(value = {ElementType.TYPE,ElementType.FIELD})
// @Retention 標(biāo)注注解的生命周期,叫做元注解,表示最終保留在class文件中,并且可以被反射機(jī)制讀取
// RetentionPolicy.SOURCE: 注解只在源碼中存在,編譯成字節(jié)碼后就不存在了
// RetentionPolicy.CLASS: 注解在源碼和字節(jié)碼中都存在,運(yùn)行時(shí)不存在(默認(rèn)值),也就是不能被反射機(jī)制讀取
// RetentionPolicy.RUNTIME: 注解在源碼、字節(jié)碼和運(yùn)行時(shí)都存在
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
    String value();
}

怎么通過(guò)反射機(jī)制讀取注解

假設(shè)user類(lèi)被注解@Component修飾

@Component("userBean")
public class User {
}
public static void main(String[] args) throws Exception {
    // 使用反射機(jī)制讀取注解
    // 獲取類(lèi)
    Class<?> userClazz = Class.forName("com.ali.component.User");
    // 判斷類(lèi)上是否有某個(gè)注解
    boolean hasAnnotation = userClazz.isAnnotationPresent(Component.class);
    if (hasAnnotation) {
        // 獲取類(lèi)上的注解對(duì)象
        Component component = userClazz.getAnnotation(Component.class);
        // 訪問(wèn)注解的屬性
        System.out.println("component value: " + component.value());
    }
}

組件掃描原理

主要是通過(guò)反射機(jī)制實(shí)例化注解標(biāo)記的類(lèi)的對(duì)象。

public static void main(String[] args) {
    // 根據(jù)一個(gè)包名,掃描這個(gè)包下面的所有類(lèi),當(dāng)這個(gè)類(lèi)有@Component注解時(shí),實(shí)例化這個(gè)類(lèi),key是@Component注解的value,value是實(shí)例化的對(duì)象
    String packageName = "com.ali.component";
    // 將包名中的“.”替換成“/”
    String path = packageName.replaceAll("\\.", "/");
    // 包是在系統(tǒng)恨路徑下的一個(gè)目錄。獲取它的絕對(duì)路徑
    String absolutePath = ClassLoader.getSystemClassLoader().getResource(path).getPath();
    // 獲取包下面的所有類(lèi)文件
    File dir = new File(absolutePath);
    File[] files = dir.listFiles();
    Arrays.stream(files).forEach(file -> {
        // 獲取類(lèi)名
        String classname = packageName + "." + file.getName().replace(".class", "");
        // 通過(guò)反射機(jī)制解析注解
        try {
            Class<?> clazz = Class.forName(classname);
            // 判斷類(lèi)上是否有某個(gè)注解
            boolean hasAnnotation = clazz.isAnnotationPresent(Component.class);
            if (hasAnnotation) {
                // 獲取類(lèi)上的注解對(duì)象
                Component component = clazz.getAnnotation(Component.class);
                // 訪問(wèn)注解的屬性
                System.out.println("component value: " + component.value());
                // 實(shí)例化這個(gè)類(lèi)
                Object obj = clazz.getDeclaredConstructor().newInstance();
                System.out.println("實(shí)例化對(duì)象: " + obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    });
}

聲明bean的注解

聲明bean的注解有:@Component 、@Controller、 @Service 、@Repository。

實(shí)際上 @Controller @Service @Repository 這3個(gè)都是@Component 的別名,本質(zhì)上就是一個(gè)注解。主要是為了增強(qiáng)代碼的可讀性。

當(dāng)這4個(gè)注解標(biāo)注在類(lèi)上是,如果沒(méi)有指定value值(也就是沒(méi)有指定bean名稱(chēng)),那么bean名稱(chēng)默認(rèn)成類(lèi)名的首字母小寫(xiě)。

選擇性實(shí)例化bean

假如有一個(gè)需求:只需要@Controller參與bean的管理。其他三個(gè)注解都不參與實(shí)例化,這種情況要怎么處理?

注意:別忘了添加配置文件的命名空間。

   <!-- 第一種方案:使用@ComponentScan自動(dòng)掃描bean
    use-default-filters="false" 表示不使用默認(rèn)的過(guò)濾器(即所有聲明bean的注解全部失效)
    @Component 、@Controller、 @Service 、@Repository 全部失效-->
    <context:component-scan base-package="com.ali.bean2" use-default-filters="false">
        <!--    自定義過(guò)濾器,指定只掃描帶有@Component注解的類(lèi)
            只有@Component生效-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
<!--            如果想讓@Service生效,可以添加下面這一行-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    </context:component-scan>
<!--    第二種方案:use-default-filters="true" 或者不寫(xiě)該屬性,表示 @Component 、@Controller、 @Service 、@Repository 全部生效-->
    <context:component-scan base-package="com.ali.bean2" >
        <!--   排除@Controller注解的類(lèi)
            只有@Controller生效-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <!--            如果想讓@Repository失效,可以添加下面這一行-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
    </context:component-scan>

負(fù)責(zé)注入的注解

@value

@value:使用@value注入的話,屬性可以不提供setter方法,負(fù)責(zé)注入簡(jiǎn)單類(lèi)型

public class User {
    @Value("Alice")
    private String name;
    @Value("22")
    private int age;
}

@value注解也可以加在setter方法上

public class User {
    private String name;
    private int age;
    @Value("Alice")
    public void setName(String name) {
        this.name = name;
    }
    @Value("22")
    public void setAge(int age) {
        this.age = age;
    }
}

@value注解也可以加在構(gòu)造方法上

public class User {
    private String name;
    private int age;
    public User(@Value("Alice") String name,@Value("22") int age) {
        this.name = name;
        this.age = age;
    }
}

@Autowired

@Autowired可以用來(lái)注入非簡(jiǎn)單類(lèi)型,翻譯為:自動(dòng)裝配。

單獨(dú)使用 @Autowired注解,默認(rèn)根據(jù)類(lèi)型裝配【默認(rèn)是byType】

注意:假如一個(gè)接口被2個(gè)或以上的類(lèi)實(shí)現(xiàn),那么這個(gè)接口對(duì)象能被 @Autowired注入嗎?這當(dāng)然不行,因?yàn)?@Autowired是根據(jù)類(lèi)型進(jìn)行裝配的。

那怎么解決這個(gè)問(wèn)題呢?

可以將@Autowired和@Qualifier聯(lián)合使用

@Autowired
// 這里指定bean的名稱(chēng),說(shuō)明是根據(jù)名稱(chēng)進(jìn)行自動(dòng)裝配的
@Qualifier("someServiceBeanForMysql") 
private SomeService someService;

@Autowired可以標(biāo)注在屬性上、setter方法上、構(gòu)造方法的參數(shù)上。

當(dāng)一個(gè)類(lèi)中的構(gòu)造方法只有一個(gè),并且構(gòu)造方法的參數(shù)和屬性能對(duì)應(yīng)上,@Autowired 可以省略 (不建議這樣用)

@Resource

@Resource注解也能完成非簡(jiǎn)單類(lèi)型的注入,那么他和 @Autowired有什么區(qū)別呢?

  • @Resource是jdk擴(kuò)展包中的,屬于jdk的一部分,所以該注解是標(biāo)準(zhǔn)注解,更加具有通用性。
  • @Autowired是spring框架自己的
  • @Resource默認(rèn)根據(jù)名稱(chēng)自動(dòng)裝配,未指定name時(shí),使用屬性名作為name,如果通過(guò)name找不到的話。會(huì)啟動(dòng)通過(guò)類(lèi)型自動(dòng)裝配。
  • @Autowired時(shí)根據(jù)類(lèi)型自動(dòng)裝配。如果要根據(jù)名字裝配,需要@Qualifier配合使用
  • @Resource用在屬性上、setter方法上
  • @Autowired用在屬性上、setter方法上、構(gòu)造方法上、構(gòu)造方法參數(shù)上。

使用@Resource時(shí)先加入相關(guān)依賴(lài)

<!--        @Resource注解的依賴(lài)-->
        <dependency>
            <groupId>jakarta.annotation</groupId>
            <artifactId>jakarta.annotation-api</artifactId>
            <version>2.1.1</version>
        </dependency>
// 進(jìn)行屬性注入
@Resource(name = "someServiceBean")
private SomeService someService;

到此這篇關(guān)于spring6注解式開(kāi)發(fā)的文章就介紹到這了,更多相關(guān)spring注解式開(kāi)發(fā)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringCloud組件OpenFeign之?dāng)r截器解讀

    SpringCloud組件OpenFeign之?dāng)r截器解讀

    這篇文章主要介紹了SpringCloud組件OpenFeign之?dāng)r截器用法。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • 淺談Sharding-JDBC強(qiáng)制路由案例實(shí)戰(zhàn)

    淺談Sharding-JDBC強(qiáng)制路由案例實(shí)戰(zhàn)

    本文主要介紹了淺談Sharding-JDBC強(qiáng)制路由案例實(shí)戰(zhàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Java參數(shù)傳遞實(shí)現(xiàn)代碼及過(guò)程圖解

    Java參數(shù)傳遞實(shí)現(xiàn)代碼及過(guò)程圖解

    這篇文章主要介紹了Java參數(shù)傳遞實(shí)現(xiàn)代碼及過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 快速掌握J(rèn)ava中注解與反射

    快速掌握J(rèn)ava中注解與反射

    本文詳細(xì)介紹了Java中注解和反射的概念及應(yīng)用,注解是用于給代碼添加元數(shù)據(jù)的標(biāo)記,如@Override、@Deprecated等,反射機(jī)制則是在運(yùn)行時(shí)獲取和操作類(lèi)的內(nèi)部信息,提高了代碼的靈活度,感興趣的朋友跟隨小編一起看看吧
    2023-06-06
  • spring與mybatis整合配置文件

    spring與mybatis整合配置文件

    本文通過(guò)實(shí)例代碼給大家介紹了spring與mybatis整合配置文件的方法,需要的朋友參考下吧
    2017-09-09
  • SpringBoot服務(wù)設(shè)置禁止server.point端口的使用

    SpringBoot服務(wù)設(shè)置禁止server.point端口的使用

    本文主要介紹了SpringBoot服務(wù)設(shè)置禁止server.point端口的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-01-01
  • java 詳解類(lèi)加載器的雙親委派及打破雙親委派

    java 詳解類(lèi)加載器的雙親委派及打破雙親委派

    這篇文章主要介紹了java 詳解類(lèi)加載器的雙親委派及打破雙親委派的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • Java單元測(cè)試Mockito的使用詳解

    Java單元測(cè)試Mockito的使用詳解

    Mockito是一個(gè)強(qiáng)大的mock工具,本文將重點(diǎn)講述Mockito的基本使用及注意事項(xiàng),以及Controller測(cè)試用例,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2021-07-07
  • SpringBoot中的YAML配置文件和日志詳解

    SpringBoot中的YAML配置文件和日志詳解

    這篇文章主要介紹了SpringBoot中的YAML配置文件和日志的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-12-12
  • springboot集成redis之字典緩存詳解

    springboot集成redis之字典緩存詳解

    Redis的字典緩存是支撐其高性能的一個(gè)關(guān)鍵因素,它使得Redis能夠以極快的速度處理大量的數(shù)據(jù),這篇文章主要介紹了springboot集成redis之字典緩存,需要的朋友可以參考下
    2024-07-07

最新評(píng)論

北海市| 延川县| 新河县| 洞口县| 东丽区| 榕江县| 黑龙江省| 呼玛县| 平塘县| 扬州市| 阿克苏市| 正定县| 呼玛县| 内丘县| 壶关县| 江源县| 精河县| 沙坪坝区| 石屏县| 利川市| 宁河县| 郴州市| 固原市| 九寨沟县| 雅安市| 龙海市| 措勤县| 达日县| 郓城县| 怀仁县| 保亭| 会东县| 大宁县| 简阳市| 鄂托克前旗| 洛浦县| 连江县| 永顺县| 元阳县| 泊头市| 行唐县|