LINUX.ORG.RU

Java Dependency Injection (JSR-330) с Google Guice

 ,


0

3

Всем привет. Решил попробовать новомодный Java'вский dependency injection. Только не тот, который толсто-ынтерпрайзный (JSR-299), а простой и базовый (JSR-330), который в принципе можно юзать вне Java EE контейнера.

В JCP написано, что reference implementation этого дела — Google Guice. Имею следующий код (обычная Java SE программа):

package com.mycompany.di;

public class Foo {

    public String foo() {
        return "Foo!";
    }
    
}   
package com.mycompany.di;

import javax.inject.Inject;

public class App {

    @Inject private Foo foo;

    public Foo getFoo() {
        return foo;
    }

    public static void main(String[] args) {

        App app = new App();
        System.out.println(app.getFoo());

    }

}

Guice 3.0 с потрохами подцепил Maven'ом. Конпеляю, запускаю — фиг там, вместо foo лежит null. ЧЯДНТ? Кастую vertexua, subwoofer, Kuka, dizza, Legioner, hizel, BattleCoder, анонимуса с домиком у озера, и кто у нас там ещё спец по Java.



Последнее исправление: cetjs2 (всего исправлений: 5)

О, надо же, я, оказывается, «спец по java». :) макскома ещё можешь позвать.

С google guice дела не имел, но «инъекция» в том же spring работает не «по волшебству». там нужно инициализировать некий контекст, и из этого контекста всё будет браться. Кроме того, Foo тоже надо проаннотировать чем-то вроде @Component/либо добавить в xml-описание контекста.

Это если очень вкратце. Подробно объяснять нет желания.

BattleCoder ★★★★★
()
Последнее исправление: BattleCoder (всего исправлений: 1)

ну вот же тут всё написано

http://code.google.com/p/google-guice/wiki/GettingStarted

 public static void main(String[] args) {
    /*
     * Guice.createInjector() takes your Modules, and returns a new Injector
     * instance. Most applications will call this method exactly once, in their
     * main() method.
     */
    Injector injector = Guice.createInjector(new BillingModule());

    /*
     * Now that we've got the injector, we can build objects.
     */
    RealBillingService billingService = injector.getInstance(RealBillingService.class);
    ...
  }
BattleCoder ★★★★★
()
Ответ на: ну вот же тут всё написано от BattleCoder

Так что же, выходит, чистым JSR-330 ограничиться нельзя? Обязательно подставлять попку под писечку Серёженьки Брина завязываться на нестандартные гугловые классы? В чём тогда был смысл JSR-330?

Отвечать не заставляю, раз нет желания/времени, пускай вопрос будет в том числе для будущих читателей.

BYHYRT
() автор топика
Ответ на: комментарий от BattleCoder
package com.mycompany.di;

import javax.inject.Inject;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;

public class App {

    @Inject private Foo foo;

    public Foo getFoo() {
        return foo;
    }

    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new AbstractModule() {
            @Override
            protected void configure() {
            }
        });
        App app = injector.getInstance(App.class);
        System.out.println(app.getFoo());
    }

}
dizza ★★★★★
()
Последнее исправление: dizza (всего исправлений: 1)
Ответ на: комментарий от BYHYRT

Обязательно подставлять попку под писечку Серёженьки Брина завязываться на нестандартные гугловые классы?

Нет. Можно использовать и собственные аннотации, и javax.inject

dizza ★★★★★
()
Ответ на: комментарий от maxcom

вопросы про создание контейнера

Имеется в виду «инжектор», наверное? Ну окей, буду пробовать Серёженькину писечку тогда. Отпишусь по результатам.

P.S. А вот интересно, можно ли Weld прикрутить к Java SE приложению? Раз он имплементация CDI (JSR-299), то и более низкий уровень там должен быть по определению

BYHYRT
() автор топика
Ответ на: комментарий от dizza

Круто, чо. Лучиков счастья в карму. Конечно, я надеялся, что удастся не завязываться на сторонние классы — но, видать, не судьба.

Поехали дальше: при попытке сделать поле foo типа IFoo (при этом class Foo implements IFoo) огребаем следующее:

[exec:exec]
Exception in thread "main" com.google.inject.ConfigurationException: Guice configuration errors:

1) No implementation for com.mycompany.di.IFoo was bound.
  while locating com.mycompany.di.IFoo
    for field at com.mycompany.di.App.foo(App.java:8)
  while locating com.mycompany.di.App

Хотя имплементация как раз есть (класс Foo), и она единственна. Чё надо ему?

BYHYRT
() автор топика
Ответ на: комментарий от dizza

Разобрался. В configure() добавил:

bind(IFoo.class).to(Foo.class);

Эка всё неочевидно и неавтоматизированно. Я думал, гораздо более лучше автоматизировано будет.

BYHYRT
() автор топика
Ответ на: комментарий от BYHYRT

Я так понимаю, JSR-330 - это стандарт, и гугловские классы - одна из реализаций.. возможно, те же аннотации использует.

ты можешь сам написать свой инжектор, с инъекциями и контекстами, если захочется =) от этого JSR-330 не становится более грязным. ;) это не часть языка. это лишь только аннотации

BattleCoder ★★★★★
()
Ответ на: комментарий от BYHYRT

Обычно все JSR - набор интерфейсов и аннотаций и их реализация должна вести себя по стандарту. Классы конкретной реализации изолированы в одном месте и вся бизнес-логика использует только стандарт

vertexua ★★★★★
()
Ответ на: комментарий от BYHYRT

На худой конец есть @ImplementedBy, но это уже имхо грязь.

dizza ★★★★★
()
Ответ на: комментарий от vertexua

Ты думал он угадывать будет имплементацию?

Но ведь не приходится угадывать имплементацию JAXP/JAXB, Bean Validation и т.п.? Не зря же SPI придумано. Вот я и решил, а вдруг...

BYHYRT
() автор топика
Ответ на: комментарий от vertexua

А, протупил. Имелась в виду имплементация инъецируемого интерфейса. (Хотя это не отменяет актуальности предыдущего сообщения)

А чё такого-то? Когда имплементация единственная — мог бы и угадать. В CDI так и сделано, например. Когда не единственная — указывать при помощи Qualifier'ов или, лучше, во внешнем конфиге (чтобы не надо было переконпелять).

BYHYRT
() автор топика
Ответ на: комментарий от BYHYRT

Никогда не понимал боязнь компиляции и боязнь конфигурации лаконичным кодом вместо развесистого xml-я, к которому еще нужны хитроумные редакторы, совмещенные с IDE.

Legioner ★★★★★
()
Ответ на: комментарий от TheKnight

Угу километровые квалифицированные имена классов ты сам вбиваешь? Не, ну можно, конечно, но в 21-м веке как то грустно.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

Дык как бы автодополнение в Eclipse работает, вроде бы. ViM для случаев, когда надо поправить параметры прям на месте и посмотреть что получилось.

TheKnight ★★★
()
Ответ на: комментарий от BYHYRT

Когда имплементация единственная — мог бы и угадать.

Ну это уже на любителя. Я например люблю, что-бы легко читалось, ради этого не обламываюсь написать что-то в явном виде еще одной строчкой. Поэтому в жуйсе всегда пишу явно байндинги, на автоматику не полагаюсь.

dizza ★★★★★
()
26 февраля 2014 г.
Ответ на: комментарий от vertexua

Блин, я аж перепугался, когда этот топик снова всплыл =)

dizza ★★★★★
()
Ответ на: комментарий от vertexua

это ужик теги тронул и меня кастануло щоле?

Deleted
()
Ответ на: комментарий от vertexua

Ещё конфигурация дефолтная будет guice-зависимая, а её переносить уже может быть неудобно. Было бы неплохо иметь стандарт для конфигурации да и инициализация через какой-нибудь SPI была бы удобней. Недостандарт, в общем. Можно было бы сделать лучше. И вообще сделать на уровне JVM инъекцию через new. Вот это было бы годно.

Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 1)
Ответ на: комментарий от Legioner

И вообще сделать на уровне JVM инъекцию через new

Покажи пожалуйста в примере, а-то у меня есть такое ощущение, что я тебя неправильно понял.

f1xmAn ★★★★★
()
Ответ на: комментарий от f1xmAn

Например в конструктор Object вставить вызов java.lang.inject.Injector.inject(this).

Т.е. пишу

class Cls { @Inject private MyService svc; … }
Cls cls = new Cls();
и cls уже инжектирован автоматом, без всяких библиотек.

Legioner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.