需要一些帮助才能理解Anotations – Spring annotations

我正在努力学习Spring和Hibernate,我真的很难理解Annotations以及它们是如何工作的。 我在互联网上看到的大部分示例都是基于注释的示例,因此我需要先了解注释的工作原理才能学习Spring或Hibernate

我知道它们是什么以及它们的用途。 我知道他们会替换xml配置。 即您可以使用注释在Java代码中直接配置bean。 我不明白的是如何使用它们以及何时可以使用它们。

试着理解如何做到这一点我认为如果我看到两者之间的差异会有所帮助。 我这里有一个简单的Spring程序。 如果我要将此示例程序转换为使用注释我需要做什么?

我想这样做的原因是因为我在下面提供的程序是我非常理解的程序(我正在阅读的Spring in Action书中的一个例子)。 如果它被转换为注释版本,我将了解注释的使用方式和位置。

有什么建议么?

提前致谢


instrumentalist.xml

          

工具主义界面

 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文档以删除配置并启用组件的自动扫描(注意:我更改了修改版本的包名称)

    

将@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乐器和歌曲属性,但我怎么知道我是否想要通过名字或类型等自动assembly

  • 如果在这个类中没有代表它的bean,我将如何自动assemblyString属性? 即乐器属性是指钢琴类,但是歌曲属性会自动assembly什么?


 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相同:

  ...  

和…一样

 @Component public class Saxophone implements Instrument{ 

请注意,默认情况下,bean的名称与类相同,只是类名的第一个字母更改为小写(因此@Component public class SomeClass将创建一个名为“someClass”的bean)。

如果要为bean命名,请将名称作为参数提供给注释:

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

和…一样

   

将参数@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自动assembly到多个类,但它们都看到相同的单个实例)。 有关不同范围的更多信息,建议您阅读官方文档 。

  • 我知道我需要@Autowire乐器和歌曲属性
    但我怎么知道我是否想要通过名字或类型等自动assembly

通常,如果您只有一个类型(接口)的实现,则按类型自动assembly更方便。 当只有一个实现时,按类型自动assembly工作,因为否则Spring无法决定实例和注入哪个实现。

在你的情况下,你有两个不同的类实现InstrumentSaxophonePiano 。 如果您尝试通过键入Instrument -field来自动assembly,那么当Spring构建Instrumentalist -bean时,您将获得exception:

 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 按名称注入自动连接的依赖 。 使用Instrument练习者中的@Qualifier注入PianoInstrument实现是通过以下方式完成的:

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

和…一样

    

请注意,没有必要(但如果你愿意,你可以@Component("piano")Piano -class中使用@Component("piano") ,因为默认命名会将类的第一个字母更改为小写,然后将其用作bean-名称。

  • 如果在这个类中没有代表它的bean,我将如何自动assemblyString属性? 即乐器属性是指钢琴类,但是歌曲属性会被自动assembly?

这是用注释绘制线条的地方(AFAIK); 你不能声明带有注释的String类型的bean(因为java.lang.String不是一个接口,不能扩展,因为它是最终的,没有接口)。 但是,使用xml-configuration,这是可能的:

    

你可以混合和匹配XML和注释,并引用注释中xml声明的bean,反之亦然,将这个bean注入Instrumentalist的’ song -field:

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

希望这有助于您了解Springs的注释并开始使用,我仍然强烈建议您阅读官方文档,因为还有很多。 如果您更喜欢阅读书籍而不是屏幕,我建议使用Appress的Spring Recipes (但我确信还有很多其他好书)。

注释可以用作标记接口之类的标记

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

Serializable只是一个标记接口,因此您的应用程序可以在运行时知道有关类的信息(基本上通过reflection)。

标记接口的问题在于您无法使用它们来标记字段或方法,这就是引入注释的原因。

假设您有此注释

 public @interface myAnnotation{ } 

您可以在运行时简单地获取由此标记修饰的方法或字段。

Hibernate和Spring尽可能多的框架需要一些关于你的代码或类的信息,如果你是这些框架的开发者,你将如何实现这一点?当然注释是最好的解决方案(至少是更清洁的方式)

不要将标记接口视为过时。使用标记也有一些优点,因为它们可确保类型安全。

  void M(Serializable s) 

你不能将任何对象传递给这个方法,除非它实现了Serializable标记。有关更多细节,请考虑阅读Effective Java,那里有一个很好的解释。