簡體   English   中英

需要一些幫助來理解Anotations - Spring注釋

[英]Need some help to understand Anotations - Spring annotations

我正在努力學習Spring和Hibernate,我真的很難理解Annotations以及它們是如何工作的。 我在互聯網上看到的大多數示例都是基於注釋的示例,所以我需要先了解注釋的工作原理才能學習Spring或Hibernate

我知道它們是什么以及它們用於什么。 我知道他們會替換xml配置。 即您可以使用注釋在Java代碼中直接配置bean。 我不明白的是如何使用它們以及何時可以使用它們。

試着理解如何做到這一點我認為如果我看到兩者之間的差異會有所幫助。 我這里有一個簡單的Spring程序。 如果我要將此示例程序轉換為使用注釋,我還需要做什么?

我想這樣做的原因是因為我在下面提供的程序是我非常理解的程序(我正在閱讀的Spring in Action書中的一個例子)。 如果將其轉換為注釋版本,我將了解注釋的使用方式和位置。

有什么建議?

提前致謝


instrumentalist.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

    <bean id="saxophone" class="com.sia.ch1.instrumentalist.Saxophone" />
    <bean id="piano" class="com.sia.ch1.instrumentalist.Piano" />

    <!--  Injecting into bean properties Ken 1 -->
    <bean id="kenny" class="com.sia.ch1.instrumentalist.Instrumentalist">
        <property name="song" value="Jingle Bells"/>
        <property name="instrument" ref="piano"/>       
    </bean> 
</beans>

樂器界面

package com.sia.ch1.instrumentalist;
public interface Instrument {
    void play();
}

樂器演奏者

package com.sia.ch1.instrumentalist;

import com.sia.ch1.performer.PerformanceException;
import com.sia.ch1.performer.Performer;

public class Instrumentalist implements Performer{

    private Instrument instrument;
    private String song;

    public Instrumentalist(){}

    public void perform() throws PerformanceException{
        System.out.print("Playing " + song + " : ");        
        instrument.play();
    }

    public void setInstrument(Instrument instrument) {
        this.instrument = instrument;
    }   

    public void setSong(String song) {
        this.song = song;
    }   
}

樂器 - 鋼琴

package com.sia.ch1.instrumentalist;

public class Piano implements Instrument{
    public Piano(){}
    public void play(){
        System.out.println("PLINK PLINK");
    }
}

樂器 - 薩克斯管

package com.sia.ch1.instrumentalist;

public class Saxophone implements Instrument{
    public Saxophone(){}
    public void play(){
        System.out.println("TOOT TOOT TOOT");
    }
}

主要課程

package com.sia.ch1.instrumentalist;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.FileSystemXmlApplicationContext;

    import com.sia.ch1.performer.PerformanceException;
    import com.sia.ch1.performer.Performer;

    public class InstrumentalistApp {

        public static void main(String[] args){
            ApplicationContext ctx = new FileSystemXmlApplicationContext("c:\\projects\\test\\conf\\instrumentalist.xml");

            Performer performer = (Performer) ctx.getBean("kenny");

            try {
                performer.perform();            
            } catch (PerformanceException e) {
                e.printStackTrace();
            }
        }   
    }

例外

package com.sia.ch1.performer;

public class PerformanceException extends Exception {

    public PerformanceException() {
        super();
        // TODO Auto-generated constructor stub
    }

    public PerformanceException(String message, Throwable cause) {
        super(message, cause);
        // TODO Auto-generated constructor stub
    }

    public PerformanceException(String message) {
        super(message);
        // TODO Auto-generated constructor stub
    }

    public PerformanceException(Throwable cause) {
        super(cause);
        // TODO Auto-generated constructor stub
    }
}

編輯1

為了嘗試轉換上面的內容,我將通過以下兩個簡單示例:

例1: http//jroller.com/habuma/entry/reducing_xml_with_spring_2

例2: http//www.theserverside.com/tutorial/Spring-Without-XML-The-Basics-of-Spring-Annotations-vs-Spring-XML-Files

我有點理解第一個URL中的例子,但第二個讓我感到困惑。 在第二個URL的示例中, SummaryConfig類的用途是什么? 看起來好像SummaryConfig類是XML文件的Java版本。 第一個示例中的示例中未使用此方法。 兩者有什么區別?

是否可以在使用注釋時將配置詳細信息放在Java類(例如SummaryConfig )中,您還可以將注釋放在bean本身中,如第一個URL中的示例所示?

謝謝

編輯2

這是我到目前為止所做的,

我修改了xml文檔以刪除配置並啟用組件的自動掃描(注意:我更改了修改版本的包名稱)

<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-2.5.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <context:component-scan base-package="com.sia.ch1.instrumentalist.annotate" />

</beans>

將@Component注釋添加到鋼琴和薩克斯風類中。 我認為這告訴容器這個類應該包含在要自動掃描的類中。 對?

package com.sia.ch1.instrumentalist.annotate;

import org.springframework.stereotype.Component;

@Component
public class Piano implements Instrument{

    public Piano(){}
    public void play(){
        System.out.println("PLINK PLINK");
    }
}

package com.sia.ch1.instrumentalist.annotate;

import org.springframework.stereotype.Component;

@Component
public class Saxophone implements Instrument{
    public Saxophone(){}
    public void play(){
        System.out.println("TOOT TOOT TOOT");
    }
}

這就是我被困的地方(工具主義課)。

  • 此類中是否需要@Component注釋? 或者只有在要從另一個類引用該類時才需要它?

  • 我知道我需要@Autowire樂器和歌曲屬性,但我怎么知道我是否想要通過名字或類型等自動裝配

  • 如果在這個類中沒有代表它的bean,我將如何自動裝配String屬性? 即樂器屬性是指鋼琴類,但是歌曲屬性會被自動裝配?


package com.sia.ch1.instrumentalist.annotate;
//
    import org.springframework.stereotype.Component;
    import com.sia.ch1.performer.PerformanceException;
    import com.sia.ch1.performer.Performer;
    //
        @Component
        public class Instrumentalist implements Performer{

        private Instrument instrument;
        private String song;

        public Instrumentalist(){}

        public void perform() throws PerformanceException{
            System.out.print("Playing " + song + " : ");        
            instrument.play();
        }

        public void setInstrument(Instrument instrument) {
            this.instrument = instrument;
        }   

        public void setSong(String song) {
            this.song = song;
        }   
    }

我認為我是對的,因為任何其他課程都不需要注釋。

謝謝

這就是我被困的地方(工具主義課)。

  • 此類中是否需要@Component注釋? 或者只有在要從另一個類引用該類時才需要它?

是的,如果您希望注釋掃描從類中為您創建bean而不需要單獨的xml配置。 由於你要求在main-method中使用bean名稱kenny (按名稱,而不是類型為Instrumentalist )實現一個Instrumentalist實現,因此它也需要命名。

使用@Component,@ Repository,@ Controller和@Service注釋的類是Spring在配置ApplicationContext時掃描的類。 這四個注釋之間的區別是語義的(區分代碼中類的作用),它們都做同樣的事情(除非你有一些只處理某些注釋類型的AOP東西;現在你不要'我需要關心這個)。

使用任何上述注釋對類進行注釋與在xml中聲明bean相同:

<bean id="saxophone" class="com.sia.ch1.instrumentalist.Saxophone"> ... </bean>

和...一樣

@Component
public class Saxophone implements Instrument{

請注意,默認情況下,bean的名稱與類相同,只是類名的第一個字母更改為小寫(因此@Component public class SomeClass將創建一個名為“someClass”的bean)。

如果要為bean命名,請將名稱作為參數提供給注釋:

@Component("kenny")
public class Instrumentalist implements Performer {

和...一樣

 <bean id="kenny" class="com.sia.ch1.instrumentalist.Instrumentalist">

將參數@Component(value="kenny")注釋的另一種方法是使用@Component(value="kenny") value = -part是可選的原因是因為注釋的工作方式如下:如果只給出一個參數而不告訴字段名稱並且注釋包含一個名為value的字段,則該參數將設置為 -field 。 如果字段名稱是其他名稱,或者您想要設置注釋的多個字段,則需要顯式定義字段: @SomeAnnotation(field1="some string", field2 = 100)@SomeAnnotation(value="someValue", anotherField="something else") 除了這一點之外,這有點不過了,但是最好知道,因為它起初可能令人困惑。

因此,@ Component-annotation告訴Spring上下文您要從帶注釋的類創建bean(或bean,請參閱@Scope )。 當沒有設置@Scope -annotation時,默認情況下將bean創建為單例(您可以將bean自動裝配到多個類,但它們都看到相同的單個實例)。 有關不同范圍的更多信息,建議您閱讀官方文檔

  • 我知道我需要@Autowire樂器和歌曲屬性
    但我怎么知道我是否想要通過名字或類型等自動裝配

通常,如果您只有一個類型(接口)的實現,則按類型自動裝配更方便。 當只有一個實現時,按類型自動裝配工作,因為否則Spring無法決定實例和注入哪個實現。

在你的情況下,你有兩個不同的類實現InstrumentSaxophonePiano 如果試圖通過自動裝配型的Instrument中的-場Instrumentalist ,你會得到當春天正在建設中的一個例外Instrumentalist -bean:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.sia.ch1.instrumentalist.annotate.Instrument] is defined: expected single matching bean but found 2: [piano, saxophone]

由於有兩個Instrument -implementations,Spring沒有足夠的信息來確定你想要在Instrumentalist注入哪一個。 這是@Qualifier -annotation的步驟。使用@Qualifier,您可以告訴Spring 按名稱注入自動連接的依賴 注入Piano的-實施Instrument使用中的@Qualifier Instrumentalist被完成:

@Component(value="kenny")
public class Instrumentalist implements Performer
{
    @Autowired
    @Qualifier("piano")
    private Instrument instrument;

和...一樣

<bean id="kenny" class="com.sia.ch1.instrumentalist.Instrumentalist">
    <property name="instrument" ref="piano"/>       
</bean>

請注意,沒有必要(但如果你願意,你可以@Component("piano")Piano -class中使用@Component("piano") ,因為默認命名會將類的第一個字母更改為小寫,然后將其用作bean-名稱。

  • 如果在這個類中沒有代表它的bean,我將如何自動裝配String屬性? 即樂器屬性是指鋼琴類,但是歌曲屬性會被自動裝配?

這是用注釋繪制線條的地方(AFAIK); 你不能用注釋聲明一個String類型的bean(因為java.lang.String不是一個接口,不能擴展,因為它是最終的,沒有接口)。 但是,使用xml-configuration,這是可能的:

<bean id="songName" class="java.lang.String">   
    <constructor-arg value="Valley of the Queens"/>
</bean>

你可以混合和匹配XML和注釋,並引用注釋中xml聲明的bean,反之亦然,將這個bean注入Instrumentalist的' song -field:

@Autowired
@Qualifier("songName")
private String song;

希望這有助於您了解Springs的注釋並開始使用,我仍然強烈建議您閱讀官方文檔,因為還有很多。 如果您更喜歡閱讀書籍而不是屏幕,我建議使用Appress的春季食譜 (但我確信還有許多其他好書)。

注釋可以用作標記接口之類的標記

class Foo implements java.io.Serializable{
 ...
}

Serializable只是一個標記接口,因此您的應用程序可以在運行時知道有關該類的信息(基本上通過反射)。

標記接口的問題在於您無法使用它們來標記字段或方法,這就是為什么要引入注釋。

假設您有此注釋

public @interface myAnnotation{
}

您可以在運行時簡單地獲取由此標記修飾的方法或字段。

Hibernate和Spring盡可能多的框架需要一些關於你的代碼或類的信息,如果你是這些框架的開發者,你將如何實現這一點?當然注釋是最好的解決方案(至少是更清潔的方式)

不要將標記接口視為過時。使用標記也有一些優點,因為它們可確保類型安全。

 void M(Serializable s)

你不能將任何對象傳遞給這個方法,除非它實現了Serializable標記。有關更多細節,請考慮閱讀Effective Java,那里有一個很好的解釋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM