Какова цель атрибута имени аннотации Spring Bean?

Я только изучаю Spring, и что-то показалось мне очень странным в конфигурациях аннотаций, использующих атрибут name в виде строки.

@Bean(name = "com.my.injected.Service")
public InjectedService injectedService() {
    return injectedService;
}

Похоже ли это имя на Spring Bean Атрибуты id и class конфигурации XML?

<bean id="..." class="...">
    <!-- collaborators and configuration for this bean go here -->
</bean>

Почему это не просто

@Bean(clazz = com.my.injected.Service.class)
public InjectedService injectedService() {
    return injectedService;
}

вместо?

Вы полностью определяете путь в обоих случаях, и фактическое использование класса облегчает вашей среде IDE определение того, что вы напортачили. Я понимаю, что конфигурация XML была первой, и, естественно, она всегда искала что-то по строке, так что это просто пережиток? Есть ли какое-то преимущество в использовании строк или большой недостаток в использовании .class?

Вопрос изначально был основан на ложной предпосылке. Я отредактировал его, чтобы разъяснить суть этой предпосылки и сделать ее менее запутанной для новых людей, которые приходят вместе. Надеюсь, я сделал это так, что данные ответы по-прежнему точно применимы; извините, если нет.


person Patrick M    schedule 07.05.2015    source источник
comment
Потому что это противоречит цели назвать что-то. Вы решили предоставить FQN. name="DasBean" так же хорош. Вы знаете, для чего предназначена эта аннотация?   -  person kolossus    schedule 07.05.2015
comment
Ха-ха, ясно, что нет. Я думаю, что я должен просто следовать примеру, который злоупотребляет аннотацией.   -  person Patrick M    schedule 07.05.2015


Ответы (2)


Имя компонента не обязательно связано с его классом или даже с каким-либо интерфейсом, который он реализует. Это имя и ничего более. Когда вы используете конфигурацию аннотации, Spring выясняет, какой именно класс или интерфейс предоставляет @Bean, как и остальная часть кода Java: либо через полное имя в коде, либо через импорт, указанный в файле. В вашем случае у вас, вероятно, есть оператор import com.my.injected.Service; в верхней части java-файла.

В вашем примере в качестве имени компонента используется полное имя класса. Это твой выбор. Вы можете использовать любой другой идентификатор. Использование полного имени может быть полезно, если ваш код предоставляет объект, имя которого точно такое же, как у другого стороннего @Bean объекта, который ваш код должен включать или использовать. Однако вы могли бы так же легко использовать name = "myService".

Имя компонента помогает Spring (и программисту приложений) различать несколько экземпляров одного и того же класса компонента, поскольку вы можете развертывать один и тот же класс в качестве компонента несколько раз. Если появляется только один экземпляр типа bean, вам не нужно присваивать ему имя вручную: Spring делает это по умолчанию.

Если у вас есть несколько bean-компонентов, которые имеют одинаковый тип или реализуют один и тот же интерфейс, и вы хотите сослаться на конкретный bean-компонент, используйте аннотацию @Qualifier.

person AlexR    schedule 07.05.2015
comment
Ах, значит, единственная причина указать полное имя в качестве атрибута name — это если вам нужно переопределить имя по умолчанию, которое, как я теперь понимаю, является именем метода или объекта, на который вы накладываете @Bean. Итак, если бы у меня были com.my.injected.Service и com.thirdparty.injected.Service в одном проекте, я мог бы использовать эту схему полного имени, чтобы устранить неоднозначность между ними. - person Patrick M; 07.05.2015
comment
Да, ты можешь. ИМХО такое длинное имя не нужно, но при желании его можно использовать. Я предпочитаю более короткие имена. Например, у вас есть 2 bean-компонента, которые реализуют InjectionServece: methodInjector и constructionInjector (я не знаю, имеют ли смысл эти имена для вас, это только для примера). В этом случае я бы назвал одного из них methodInjector, другого constructorInjector. - person AlexR; 07.05.2015

Аннотация @Bean предназначен для обеспечения весеннего боба. Тип предоставляемого bean-компонента будет тем же типом класса/интерфейса, который вы определяете в возвращаемом методе. Таким образом, вместо объявления возврата конкретного класса в методе вместо этого верните верхний (абстрактный) класс/интерфейс.

Представьте себе этот случай:

public interface MyEntityDao {
    MyEntity get(String id);
}

@Repository
public class MyEntityDaoDatabaseImpl implements MyEntityDao {
    @Override
    public MyEntity get(String id) {
        /* implementation that goes to database every time */
    }
}

@Repository
public class MyEntityDaoCacheImpl implements MyEntityDao {
    @Override
    public MyEntity get(String id) {
        /* implementation that looks the data
           up in cache, never in database */
    }
}

@Configuration
public class MyAppConfiguration {
    @Bean
    public MyEntityDaoDatabaseImpl method1() {
        return new MyEntityDaoDatabaseImpl();
    }
    @Bean
    public MyEntityDaoCacheImpl method2() {
        return new MyEntityDaoCacheImpl();
    }
}

@Service
public class MyEntityService {
    @Autowired //what to inject here?
    MyEntityDao dao;
}

В случае выше есть две реализации предлагаемого интерфейса. Как фреймворк может понять, какую реализацию использовать, кроме имени?

@Service
public class MyEntityService {
    @Autowired
    @Qualifier("properBeanNameToInject")
    MyEntityDao dao;
}
person Luiggi Mendoza    schedule 07.05.2015
comment
Действительно ли имя дает вам возможность управлять интерфейсом по сравнению с типом реализации? На странице, на которую вы ссылаетесь, указано @Bean(name={"b1","b2"}) // bean available as 'b1' and 'b2', but not 'myBean', что явно подразумевает, что имя просто предоставляет синтаксический сахар, но вы хотите ссылаться на введенный объект, как в других классах. - person Patrick M; 07.05.2015
comment
@PatrickM добавил случай, когда имя становится более актуальным, чем высший класс/интерфейс. - person Luiggi Mendoza; 07.05.2015