需要一些帮助来理解Anotations - Spring注释

zig*_*ggy 5 java oop spring annotations dependency-injection

我正在努力学习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>
Run Code Online (Sandbox Code Playgroud)

乐器界面

package com.sia.ch1.instrumentalist;
public interface Instrument {
    void play();
}
Run Code Online (Sandbox Code Playgroud)

乐器演奏者

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;
    }   
}
Run Code Online (Sandbox Code Playgroud)

乐器 - 钢琴

package com.sia.ch1.instrumentalist;

public class Piano implements Instrument{
    public Piano(){}
    public void play(){
        System.out.println("PLINK PLINK");
    }
}
Run Code Online (Sandbox Code Playgroud)

乐器 - 萨克斯管

package com.sia.ch1.instrumentalist;

public class Saxophone implements Instrument{
    public Saxophone(){}
    public void play(){
        System.out.println("TOOT TOOT TOOT");
    }
}
Run Code Online (Sandbox Code Playgroud)

主要课程

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();
            }
        }   
    }
Run Code Online (Sandbox Code Playgroud)

例外

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
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑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>
Run Code Online (Sandbox Code Playgroud)

将@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");
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是我被困的地方(工具主义课).

  • 此类中是否需要@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;
        }   
    }
Run Code Online (Sandbox Code Playgroud)

我认为我是对的,因为任何其他课程都不需要注释.

谢谢

esa*_*saj 5

这就是我被困的地方(工具主义课).

  • 此类中是否需要@Component注释?或者只有在要从另一个类引用该类时才需要它?

是的,如果您希望注释扫描从类中为您创建bean而不需要单独的xml配置.由于您在main方法中要求Instrumentalist使用bean名称kenny(按名称,而不是按类型Instrumentalist)实现,因此还需要对其进行命名.

使用@Component,@ Repository,@ Controller和@Service注释的类是Spring在配置ApplicationContext时扫描的类.这四个注释之间的区别是语义的(区分代码中类的作用),它们都做同样的事情(除非你有一些只处理某些注释类型的AOP东西;现在你不要'我需要关心这个).

使用任何上述注释对类进行注释与在xml中声明bean相同:

<bean id="saxophone" class="com.sia.ch1.instrumentalist.Saxophone"> ... </bean>
Run Code Online (Sandbox Code Playgroud)

和...一样

@Component
public class Saxophone implements Instrument{
Run Code Online (Sandbox Code Playgroud)

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

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

@Component("kenny")
public class Instrumentalist implements Performer {
Run Code Online (Sandbox Code Playgroud)

和...一样

 <bean id="kenny" class="com.sia.ch1.instrumentalist.Instrumentalist">
Run Code Online (Sandbox Code Playgroud)

将参数赋予注释的另一种方法是使用@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无法决定实例和注入哪个实现.

在你的情况下,你有两个不同的类实现Instrument-interface:SaxophonePiano.如果你尝试通过键入Instrument-field的-field Instrumentalist,你会在Spring构造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]
Run Code Online (Sandbox Code Playgroud)

由于有两个Instrument实现,Spring没有足够的信息来确定你想要注入哪一个Instrumentalist.这是@Qualifier -annotation的步骤.使用@Qualifier,您可以告诉Spring 按名称注入自动连接的依赖.要注入Piano-inmplementation Instrument使用@Qualifier,请执行以下Instrumentalist操作:

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

和...一样

<bean id="kenny" class="com.sia.ch1.instrumentalist.Instrumentalist">
    <property name="instrument" ref="piano"/>       
</bean>
Run Code Online (Sandbox Code Playgroud)

请注意,没有必要(但如果您愿意,可以@Component("piano")Piano-class中使用),因为默认命名会将类的第一个字母更改为小写,然后将其用作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>
Run Code Online (Sandbox Code Playgroud)

您可以混合并匹配XML和注释,并引用注释中的xml中声明的bean,反之亦然,将此bean注入Instrumentalists song-field:

@Autowired
@Qualifier("songName")
private String song;
Run Code Online (Sandbox Code Playgroud)

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