我正在尝试学习Spring和Hibernate,而且我真的很难理解Annotations及其工作方式。我在Internet上看到的大多数示例都是基于注释的示例,因此在学习Spring或Hibernate之前,我需要首先了解注释的工作方式。
我对它们是什么以及它们的用途有所了解。我知道他们取代了xml配置。 IE。您可以使用注释直接在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>
仪器接口(interface)
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();
}
}
}
异常(exception)
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使我有些困惑。在第二个URL的示例中,
SummaryConfig
类的用途是什么?看来SummaryConfig
类是XML文件的Java版本。在第一个示例的示例中未使用此方法。两者有什么区别?难道是当您使用批注时,您可以将配置详细信息放在Java类中(例如
SummaryConfig
),也可以如第一个URL中的示例那样将批注放置在bean本身中吗?谢谢
编辑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");
}
}
这就是我被困住的地方(乐器演奏家课)。
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;
}
}
我认为我是对的,其他任何类都不需要注释。
谢谢
最佳答案
This is where i am stuck (the Instrumentalist class).
- Is the @Component annotation required in this class? Or is it only required if the class is to be referenced from another class?
是的,是的,如果您希望注释扫描从类为您创建Bean,而无需单独的xml配置。由于您在主方法中要求使用Bean名称kenny(按名称,而不是按
Instrumentalist
类型)的Instrumentalist
实现,因此也需要对其进行命名。在配置ApplicationContext时,Spring会使用@ Component,@ Repository,@ Controller和@Service注释的类。这四个注释之间的区别是语义上的(区别了类在代码中的作用),它们都做完全相同的事情(除非例如,您有一些仅处理某些注释类型的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")
。之所以值= -part是可选的,是因为注释的工作方式如下:如果仅给出一个参数而不告知字段名称,并且注释包含一个名为值的字段,则该参数将设置为值-字段。如果字段名称是其他名称,或者您要设置注释的多个字段,则需要显式定义以下字段:@SomeAnnotation(field1="some string", field2 = 100)
或@SomeAnnotation(value="someValue", anotherField="something else")
。这一点不重要,但是很高兴知道,因为起初可能会造成混淆。因此,@ Component-annotation告诉Spring上下文您想从带注释的类中创建一个bean(或多个bean,请参见@Scope)。当未设置@Scope -annotation时,默认情况下将将这些bean创建为单例(您可以将bean自动连接到多个类,但是它们都看到相同的单个实例)。 For more information about the different scopes, I suggest reading the official documentation。
- 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
通常,如果只有一个类型(接口(interface))的实现,则按类型 Autowiring 会更方便。在只有一个实现的情况下,按类型进行 Autowiring 是可行的,因为否则Spring不能决定实例和注入(inject)哪个实现。
在您的情况下,您有两个实现
Instrument
-interface的不同类:Saxophone
和Piano
。如果尝试按类型自动连接Instrument
的Instrumentalist
-field,则在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]
由于有两种
Instrument
实现,Spring没有足够的信息来确定要在Instrumentalist
中注入(inject)哪一种。这就是@Qualifier -annotation介入的地方。使用@Qualifier,您告诉Spring注入(inject)自动连接的依赖项,并使用命名。要在Piano
中使用@Qualifier注入(inject)Instrument
-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")
-class中使用Piano
,因为默认命名会将类的首字母更改为小写,然后将其用作Bean名称。
- 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?
这是用注释绘制线条的地方(AFAIK);您不能用注解声明String类型的Bean(因为java.lang.String不是接口(interface),无法扩展,因为它是最终的,并且没有接口(interface))。但是,使用xml配置,这是可能的:
<bean id="songName" class="java.lang.String">
<constructor-arg value="Valley of the Queens"/>
</bean>
您可以混合使用XML和注解,并从注解引用xml中声明的bean,反之亦然,以将该bean注入(inject)
Instrumentalist
的song
-field:@Autowired
@Qualifier("songName")
private String song;
希望这可以帮助您大致了解Springs的注释并开始使用,我仍然强烈建议您阅读官方文档,因为还有很多其他内容。如果您更喜欢阅读书籍而不是从屏幕上阅读,我建议使用Appress's Spring Recipes(但我敢肯定,还有很多其他好书)。
关于java - 需要一些帮助来理解注释-Spring注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8862909/