需要一些帮助来理解注解 - Spring 注解 [英] Need some help to understand Anotations - Spring annotations

查看:33
本文介绍了需要一些帮助来理解注解 - Spring 注解的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习 Spring 和 Hibernate,但我真的很难理解注释及其工作原理.我在 Internet 上看到的大多数示例都是基于注释的示例,因此我需要先了解注释的工作原理,然后才能学习 Spring 或 Hibernate

I am trying to learn Spring and Hibernate and i am really struggling to understand Annotations and how they work. Most of the example i am seeing on the Internet are annotation based examples so i need to understand how the annotations work first before i can learn Spring or Hibernate

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

I have an idea of what they are and what they are used for. I know that they replace the xml configuration. I.e. You can configure beans directly within Java code using annotations. What i dont understand is how to use them and when they can be used.

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

Trying to understand how this can be done i think it would be helpful if i see the difference between the two. I have here a simple Spring program. If i was to convert this sample program to use annotations what would i need to do?

我想这样做的原因是因为我在下面提供的程序是我非常理解的程序(我目前正在阅读的 Spring in Action 书中的一个例子).如果将其转换为注释版本,我将了解如何以及在何处使用注释.

The reason i want to do it this way is because the program i have provided below is one that i understand very well (an example from the Spring in Action book that i am currently reading). If it is converted to an annotations version i will get an idea as to how and where annotations can be used.

有什么建议吗?

提前致谢

乐器师.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

为了尝试转换上述内容,我将通过以下两个简单示例:

Edit 1

To try and convert the above i am going through these two simple examples:

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

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

我有点理解第一个 URL 中的示例,但第二个让我有点困惑.在第二个 URL 的示例中,SummaryConfig 类的用途是什么?SummaryConfig 类看起来好像是 XML 文件的 Java 版本.在第一个示例中的示例中没有使用这种方法.两者有什么区别?

I kind of understand the examples in the first URL but the second one confused me a bit. In the example in the second URL, what is purpose of the SummaryConfig class? It looks as though the SummaryConfig class is a Java version of the XML file. This approach was not used in the example in the first example. What is the difference between the two?

是不是当你使用注解时,你可以把配置细节放​​在一个Java类中(例如SummaryConfig),你也可以把注解放在bean本身中,就像第一个例子中的那样网址?

Could it be that when you using annotations you can put the configuration details in a Java class (e.g. SummaryConfig) and you can also put the annotations in the beans themselves as in the examples in the first URL?

谢谢

这是我到目前为止所做的,

Here is what i have done so far,

我修改了xml文档,去掉了配置,开启了组件自动扫描(注意:修改后的版本我改了包名)

I have modified the xml document to remove the configuration and enable the auto-scan of components (Note: i changed the package name for the modified versions)

<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>

在 Piano 和 Saxophone 类中添加了 @Component 注释.我认为这告诉容器该类应该包含在要自动扫描的类中.对?

Added the @Component annotation to the Piano and Saxophone classes. I think this tells the container that this class should be included in the classes to be auto-scanned. right?

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");
    }
}

这就是我被困的地方(器乐演奏者课程).

This is where i am stuck (the Instrumentalist class).

  • 这个类需要@Component注解吗?还是仅当该类要从另一个类引用时才需要?

  • Is the @Component annotation required in this class? Or is it only required if the class is to be referenced from another class?

我知道我需要@Autowire 乐器和歌曲属性,但我怎么知道我是要按名称还是按类型等自动装配

I know that i need to @Autowire the instrument and song properties but how do i know if i want to autowire byname or bytype etc

如果在这个类中没有代表它的 bean,我将如何自动装配 String 属性?即乐器属性将引用钢琴类,但歌曲属性将自动装配什么?

How would i autowire the String property if in this class there is no bean that represents it? i.e the instrument property would refer to the piano class but what would the song property be autowired with?

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;
        }   
    }

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

I think i am right in that no annotations are required on any of the other classes.

谢谢

推荐答案

这就是我被困的地方(器乐演奏者课程).

This is where i am stuck (the Instrumentalist class).

  • 这个类需要@Component注解吗?或者仅仅是如果要从另一个类引用该类,则需要?

是的,如果您希望注释扫描从类中为您创建 bean,而无需单独的 xml 配置.由于您在主方法中要求使用 bean 名称 kenny(按名称,而不是按类型 Instrumentalist)实现 Instrumentalist -implementation,它也需要命名.

Yes, it is, if you want the annotation scanning to create the bean from the class for you without separate xml-configuration. Since you ask for an Instrumentalist -implementation with the bean name kenny (by name, not by type Instrumentalist) in your main-method, it also needs to be named.

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

Classes annotated with @Component, @Repository, @Controller and @Service are the ones that Spring scans for when the ApplicationContext is configured. The difference between these four annotations is semantical (differentiating the role of the class in the code), they all do exactly the same thing (unless for example you have some AOP-stuff that handles only certain annotation-types; for now you don't need to care about this).

使用上述任何注解来注解一个类与在 xml 中声明一个 bean 相同:

Annotating a class with of any of the aforementioned annotation is same as declaring a bean in the xml:

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

@Component
public class Saxophone implements Instrument{

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

Note that by default the bean is named same as the class, except the first letter of the class name is changed to lowercase (so @Component public class SomeClass would create a bean called "someClass").

如果你想给你的bean命名,你可以把名字作为注解的参数:

If you want to name your bean, you give the name as a parameter to the annotation:

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

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

另一种为注释提供参数的方法是使用 @Component(value="kenny").value= -part 是可选的,是因为注释的工作方式是这样的:如果只给出一个参数而不告诉字段名称,并且注释包含一个名为 value,该参数将设置为-字段.如果字段名是别的,或者要设置多个注解字段,则需要明确定义字段:@SomeAnnotation(field1="some string", field2 = 100) 或 <代码>@SomeAnnotation(value="someValue", anotherField="something else").这有点离题,但很高兴知道,因为一开始可能会令人困惑.

Another way to give the parameter to the annotation would be using @Component(value="kenny"). The reason the value= -part is optional, is because the annotations work like this: if there is only one parameter given without telling the field-name and the annotation contains a field called value, the parameter will be set to the value-field. If the field name is something else, or you want to set multiple fields of the annotation, you need to explicitly define the fields: @SomeAnnotation(field1="some string", field2 = 100) or @SomeAnnotation(value="someValue", anotherField="something else"). This is a bit besides the point, but it's good to know, as it can be confusing at first.

因此,@Component-annotation 告诉 Spring 上下文您要创建一个 bean(或 bean,参见 @Scope) 来自带注释的类.当没有 @Scope 注释集时,bean 将默认情况下创建为单例(您可以将 bean 自动装配到多个类,但它们都看到相同的单个实例).了解更多信息关于不同的范围,我建议阅读官方文档.

So, the @Component-annotation tells the Spring context that you want to create a bean (or beans, see @Scope) from the annotated classes. When there's no @Scope -annotation set, the beans will be created as singletons by default (you can autowire the bean to multiple classes, but they all see the same, single instance). For more information about the different scopes, I suggest reading the official documentation.

  • 我知道我需要@Autowire 乐器和歌曲属性
    但是我怎么知道我是要按名称自动装配还是按类型自动装配等

通常,如果您只有一个类型(接口)的单一实现,按类型自动装配会更方便.当只有一个实现时,按类型自动装配是有效的,否则 Spring 无法决定要实例化和注入哪个实现.

Usually, if you only have a single implementation of a type (interface), it's more convenient to autowire by type. Autowiring by type works, when there is only a single implementation, because otherwise Spring cannot decide which implementation to instance and inject.

在您的情况下,您有两个不同的类实现了 Instrument 接口:SaxophonePiano.如果您尝试按类型自动装配 InstrumentalistInstrument-字段,当 Spring 构建 Instrumentalist-bean 时,您将收到异常:

In your case you have two different classes implementing the Instrument-interface: Saxophone and Piano. If you try to autowire by-type the Instrument-field of the Instrumentalist, you will get an exception when Spring is constructing the 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 实现,Spring 没有足够的信息来确定您要在 Instrumentalist 中注入哪一个.这是 @Qualifier 注释介入的地方.使用@Qualifier,您告诉 Spring 注入自动装配的依赖项按名称.使用 Instrumentalist 中的 @Qualifier 注入 Piano 实现的 Instrument 是通过以下方式完成的:

Since there are two Instrument-implementations, Spring doesn't have enough information to determine which one you want injected in the Instrumentalist. This is where the @Qualifier -annotation steps in. With the @Qualifier, you tell Spring to inject the autowired dependency by-name. To inject the Piano-implementation of Instrument using the @Qualifier in the Instrumentalist is done by:

@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>

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

Note that there's no need (but you can if you want to) to use @Component("piano") in the Piano-class, as the default naming changes the first letter of the class to lowercase and then uses it as the bean-name.

  • 如果在这个类中没有 bean,我将如何自动装配 String 属性代表吗?即,乐器属性将引用钢琴类,但是 > 歌曲属性会自动装配什么?

这是用注释绘制线条的地方(AFAIK);您不能使用注释声明 String 类型的 bean(因为 java.lang.String 不是接口,不能扩展,因为它是最终的并且没有接口).但是,使用 xml 配置,这是可能的:

This is where the line is drawn with annotations (AFAIK); you cannot declare a bean of type String with annotations (Since java.lang.String is not an interface, cannot be extended as it's final and doesn't have an interface). However, with xml-configuration this is possible:

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

您可以混合搭配 XML 和注解,并从注解中引用 xml 中声明的 bean,反之亦然,将此 bean 注入 Instrumentalists 的 song-字段:

You can mix-and-match XML and annotations, and refer to beans declared in xml from annotations and vice versa, to inject this bean into Instrumentalists' song-field:

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

希望这能帮助您大致了解 Springs 的注释并开始使用,我仍然强烈建议您阅读官方文档,因为还有很多.如果您更喜欢阅读书籍而不是从屏幕上阅读,我建议例如 Appres's Spring Recipes(但我肯定还有很多其他的好书).

Hope this helped you to understand Springs' annotations in general and get started, I'd still strongly suggest you to read the official documentation, as there's a LOT more. If you prefer to read books instead of from screen, I'd suggest for example Appress's Spring Recipes (but I'm sure there are many other good books too).

这篇关于需要一些帮助来理解注解 - Spring 注解的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆