Нужна помощь, чтобы понять аннотации - весенние аннотации - PullRequest
5 голосов
/ 14 января 2012

Я пытаюсь изучить Spring и Hibernate, и я действительно изо всех сил пытаюсь понять Аннотации и как они работают. Большинство примеров, которые я вижу в Интернете, представляют собой примеры на основе аннотаций, поэтому мне нужно сначала понять, как работают аннотации, прежде чем я смогу изучать Spring или Hibernate

У меня есть представление о том, что они из себя представляют и для чего они используются. Я знаю, что они заменяют конфигурацию xml. То есть Вы можете настроить bean-компоненты непосредственно в Java-коде, используя аннотации. Что я не понимаю, так это как их использовать и когда их можно использовать.

Пытаясь понять, как это можно сделать, я думаю, было бы полезно, если бы я увидел разницу между ними. У меня здесь простая весенняя программа. Если бы я должен был преобразовать этот пример программы для использования аннотаций, что бы мне нужно было сделать?

Причина, по которой я хочу сделать это, заключается в том, что программа, которую я представил ниже, является той, которую я очень хорошо понимаю (пример из книги «Весна в действии», которую я сейчас читаю). Если он преобразуется в версию аннотации, я получу представление о том, как и где можно использовать аннотации.

Есть предложения?

Заранее спасибо


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

Чтобы попытаться преобразовать вышесказанное, я рассмотрю два простых примера:

Ex1: 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 является Java-версией XML-файла. Этот подход не использовался в примере в первом примере. В чем разница между ними?

Может ли быть так, что, когда вы используете аннотации, вы можете поместить детали конфигурации в класс Java (например, SummaryConfig), а также вы можете поместить аннотации в самих компонентах, как в примерах в первом 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 свойства инструмента и песни, но как я могу узнать, хочу ли я автоматически передавать по имени или по типу и т. Д.

  • Как бы я автоматически связал свойство 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;
        }   
    }

Я думаю, что я прав, в том, что ни один из других классов не требует аннотаций.

Спасибо

Ответы [ 2 ]

5 голосов
/ 16 января 2012

Вот где я застрял (класс инструменталистов).

  • Требуется ли аннотация @Component в этом классе? Или это только требуется, если на класс нужно ссылаться из другого класса?

Да, если вы хотите, чтобы сканирование аннотаций создавало для вас компонент из класса без отдельной xml-конфигурации. Поскольку вы запрашиваете Instrumentalist -реализацию с именем bean kenny (по имени, а не по типу Instrumentalist) в вашем main-методе, его также необходимо назвать.

Классы, аннотированные @Component, @Repository, @Controller и @Service, - это те, которые Spring сканирует при настройке ApplicationContext. Разница между этими четырьмя аннотациями семантическая (дифференцирующая роль класса в коде), они все делают одно и то же (если, например, у вас нет AOP-материала, который обрабатывает только определенные типы аннотаций; сейчас вы не не нужно заботиться об этом).

Аннотирование класса любой из вышеупомянутой аннотации аналогично объявлению bean-компонента в xml:

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

совпадает с

@Component
public class Saxophone implements Instrument{

Обратите внимание, что по умолчанию bean-компонент назван так же, как и класс, за исключением того, что первая буква имени класса изменяется на нижний регистр (поэтому @Component public class SomeClass создаст bean-компонент с именем "someClass").

Если вы хотите назвать свой компонент, вы даете имя в качестве параметра для аннотации:

@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"). Это немного помимо сути, но это хорошо знать, так как поначалу это может сбить с толку.

Итак, аннотация @ Component сообщает контексту Spring, что вы хотите создать bean-компонент (или bean-компоненты, см. @ Scope ) из аннотированных классов. Когда нет аннотации @ Scope , бины будут создаваться как синглтоны по умолчанию (вы можете автоматически связывать бин с несколькими классами, но все они видят один и тот же экземпляр). Для получения дополнительной информации о различных областях, я предлагаю прочитать официальную документацию .

  • Я знаю, что мне нужно @Autowire свойства инструмента и песни
    но как я могу узнать, хочу ли я автоматически передавать по имени или по типу и т. д.

Обычно, если у вас есть только одна реализация типа (интерфейса), удобнее выполнять автоматическое подключение по типу. Автопроводка по типу работает, когда существует только одна реализация, потому что иначе Spring не может решить, какую реализацию копировать и внедрять.

В вашем случае у вас есть два разных класса, реализующих Instrument -интерфейс: Saxophone и Piano. Если вы попытаетесь выполнить автоматическое подключение с помощью поля Instrument поля 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]

Поскольку существует две реализации Instrument, Spring не имеет достаточно информации, чтобы определить, какую из них вы хотите внедрить в Instrumentalist. Это то место, где вступает аннотация @ Qualifier . С помощью @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 -классе, так как при присвоении имени по умолчанию первая буква класса изменяется на строчные, а затем используется в качестве bean-компонента. -name.

  • Как бы я автоматически связал свойство String, если в этом классе нет бина, который представляет это? то есть свойство инструмента будет относиться к классу фортепиано, но с чем будет автоматически связано свойство песни?

Здесь линия рисуется с аннотациями (AFAIK); вы не можете объявить bean-компонент типа String с аннотациями (поскольку java.lang.String не является интерфейсом, его нельзя расширять, так как он является окончательным и не имеет интерфейса). Однако с xml-конфигурацией это возможно:

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

Вы можете смешивать и сопоставлять XML и аннотации, а также ссылаться на bean-компоненты, объявленные в xml из аннотаций и наоборот, чтобы вставить этот bean-компонент в *1000* s 'song -field:

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

Надеюсь, что это помогло вам понять аннотации Springs в целом и начать, я все равно настоятельно рекомендую вам прочитать официальную документацию, так как есть еще много. Если вы предпочитаете читать книги вместо экрана, я бы предложил, например, Весенние рецепты Appress (но я уверен, что есть и много других хороших книг).

2 голосов
/ 14 января 2012

Аннотации могут использоваться в качестве маркеров, таких как интерфейсы маркеров

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

Serializable - это просто интерфейс маркера, чтобы ваше приложение могло знать информацию о класс во время выполнения (в основном по отражению).

Проблема с интерфейсами маркеров заключается в том, что вы не можете использовать их для маркировки полей или методов, поэтому были введены аннотации.

предположим, что у вас есть эта аннотация

public @interface myAnnotation{
}

вы можете просто получить методы или поля, которые оформлены этим маркером во время выполнения.

Hibernate и Spring, так как многим фреймворкам требуется некоторая информация о вашем коде или классах, как бы вы достигли этого, если бы вы были разработчиком этих фреймворков? Конечно, аннотации - лучшее решение (по крайней мере, более чистый способ)

Не считайте интерфейсы маркеров устаревшими. Есть также некоторые преимущества использования маркеров, поскольку они обеспечивают безопасность типов.

 void M(Serializable s)

вы не можете передать объект этому методу, если он не реализует маркер Serializable. Для более подробной информации читайте Effective Java , там есть отличное объяснение.

...