JavaRush/Java блог/Архив info.javarush/Dependency Injection. Помогите чайнику!
BigVOVA
30 уровень

Dependency Injection. Помогите чайнику!

Статья из группы Архив info.javarush
участников
Я уже вовсю юзаю Spring, где на каждый "пук" ложиться @autowired. Все отлично работает, удобно и просто до обалдения. Но в один прекрасный момент я понял, что я ничего не понял) Как это работает? Коллеги! Помогите разобраться... Dependency Injection. Помогите чайнику! - 1Интересует пример для чайников... Как без Spring проинжектить экземпляр одного класса в поле другого? Может ссылку простую дадите, или в комментах объясните.
Комментарии (21)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
k1per
Уровень 19
26 января 2016, 17:28
Через Reflection API. То есть Cat не через new будет созжаваться, а через newInstance()(и вообще не мы создаем бин), куда в качестве параметра будет передан подходящий Bean, опять же, созданный контекстом на основе XML-конфигурации Spring-a и аннотаций. То есть context нам делает необходимый Inject.

Так мне кажется, хе-хе, но я могу ошибаться. Если кто поправит, буду очень рад.

Ппц, как-то сложно написал. Вообщем, все реализовано через механизм рефлексии.
BigVOVA
Уровень 30
26 января 2016, 17:37
Вот, вот, вот! Я в эту сторону и капаю. Но хочу создать бин (по сути просто экземпляр класса) сам, без спринга. Как это сделать? И как потом именно его (подходящий по контексту) с помощью аннотации проинжектить?
k1per
Уровень 19
26 января 2016, 17:41
Находишь один бин с помощью рефлексии. Создаешь анимал через newInstance.
Находить второй бин через рефлекцию. Создаешь кота через newInstance конструктора, в качестве аргумента передаешь первый бин.

Я бы так сделал, но зачем тебе собственный велосипед придумывать?
BigVOVA
Уровень 30
26 января 2016, 18:00
А можешь на моих котах и в реальном коде? Все что ты написал есть в доках и я это читал, и в общем приближении понимаю суть. Но хочется понять глубже. И я так устроен, что мне проще понять на реальном примере. Да да, в детстве свой первый велосипед я разобрал в первый же вечер. И не ради того, что бы изобрести подобный, а ради понимания как работает задняя каретка. Почему педали в одном направления входят в сцепление с задним колесом, а в другом нет.
Fry
Уровень 41
26 января 2016, 23:44
На твоих котах вот такую структуру создать будет очень проблематично. Так как спринг не просто инжектит бин в @autowired. Он его инициализирует с нужными параметрами.

В середине там только джава, и используются инструметны джавы, в т. ч. и отражение.
Бин проходит несколько этапов инициализации, от создания биндифинишинов до обработки бина пост процессором (ами)
тут кратко о каждом этапе.
BigVOVA
Уровень 30
27 января 2016, 15:59
Статейку эту я так же читал, она действительно помогает разобраться в Spring'е.
Ладно, мой вопрос видимо тяжеловат для нашего сообщества. Это, кстати, вопрос с собеседования когда декларируешь знание Spring или других контейнеров, правда, выше джуниора.
k1per
Уровень 19
27 января 2016, 16:13
Ты меня прости, но от джуна и, наверно, от мидла не требует умение написать собственный IoC framework
BigVOVA
Уровень 30
27 января 2016, 16:33
О Боже! Тут речь не идет о написании framework'а аля Spring. Достаточно создать два бина и показать их взаимодействие через Reflection. На живом, но примитивном примере. Нам не нужно парсировать конфиг (его нет), нам не нужна фабрика (мы и так знаем все о классах которые будут бинамии их всего 2), нам не нужны пред и пост процессы. Диаграмма приведенная Fry избыточно в моем случае.
Fry
Уровень 41
27 января 2016, 19:27
Ну, аннотация тут не к чему. Аннотация служит маркером и иногда используются параметры аннотации.
Для такого класса Кет
public class Cat {

    @MyAutoWired
    private Animal animal;
}
метод инжекта приблизительно такой. Это частный случай, без дженериков и типов классов, без проверок и написан на скорую руку за 5 мин.

public static Cat initialize() throws IllegalAccessException, InstantiationException {

        Cat cat = null;

        Field[] declaredFields = Cat.class.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            if (declaredField.getAnnotations() != null ) {
                for (Annotation annotation : declaredField.getAnnotations()) {
                    if (annotation instanceof MyAutoWired) {
                         cat = Cat.class.newInstance();
                         declaredField.setAccessible(true);
                         declaredField.set(cat, Animal.class.newInstance());
                    }
                }
            }
        }

        return cat;
    }
Далее это все проксируется и выдается как бин из класса Cat с проинициализированым полем private Animal animal;.
Это самый примитивизм для поля. Для конструкторов или сетеров и гетеров будет ещё сложнее.

И чуть не забыл, аннотацию надо отмаркать
@Retention(RetentionPolicy.RUNTIME)
BigVOVA
Уровень 30
27 января 2016, 21:53
Вот за это МЕГА СПАСИБО!
Fry
Уровень 41
28 января 2016, 10:29
только смысл то в этом? В спринге все совсем по другому. В некоторых случаях юзаются сеттеры, так как операции отражения слишком дорогие.
BigVOVA
Уровень 30
29 января 2016, 00:54
Хммм, ну тут философия пошла. Я в свое время процессор КР580ВМ80А на стенде «потактово» гонял, регистры тумблерами устанавливал, а читал светодиодами. Есть в этом смысл? Хз… Так и тут. Вот хочу знать и все тут)))

Совсем оффтоп… А предшественник то вм80 еще и эстетически прекрасным был!

BigVOVA
Уровень 30
26 января 2016, 17:11
Коллеги! Или я неправильно написал, или Вы не дочитали. Как работает di, ioc в Spring в прикладной плоскости мне понятно. Я не могу догнать как реализует di сам Spring. Т.е. давайте представим, что Spring еще не придумали) Допустим у нас есть класс Cat и нужно проинжектить в него Animal, пусть на уровне конструктора используя аннотацию @MyAutowired. Может кто реализовать @MyAutowired так, чтобы на примере был понятен механизм?

public class Animal {
    
    private int tail = 1;
    private int feet = 4;

    public Animal() {
    }

    public int getTail() {
        return tail;
    }

    public int getFeet() {
        return feet;
    }
}


public class Cat {

    private Animal animal;

    @MyAutoWired
    public Cat(Animal animal) {
        this.animal = animal;
    }
}


public @interface MyAutoWired {
    //ToDo
}
Fry
Уровень 41
26 января 2016, 17:24
а в сорцах посмотреть?
BigVOVA
Уровень 30
26 января 2016, 17:30
в сорцах Spring? Я же писал… Помогите чайнику. Для меня реализация Spring это слишком сложный пример. И слишком громоздкий для академических целей.
Fry
Уровень 41
26 января 2016, 23:15
там кроме джавы ничего больше нет. Рано или поздно сорцы читать придётся. Дырочек то и в спрингу хватает.
k1per
Уровень 19
26 января 2016, 09:42
Всем привет. Сейчас читаю Spring in Action. Автор отлично объясняет зачем он создал Spring, как работает Dependency Injection и Aspect-Oriented Programming, а также остальные модули Spring-а
Качаем и читаем тут
mrserfr
Уровень 33
26 января 2016, 09:56
спасибо, книга действительно стоящая
k1per
Уровень 19
26 января 2016, 10:06
Пожалуйста ;)
Fry
Уровень 41
25 января 2016, 23:57
Наверное пора читать спеки. Есть много туториалов по спрингу на русском языке
Например:
Понимание контейнера инверсии контроля (IoC) Spring

А лучше тут читать

Ну или на худой конец Бориcова посмотреть
AndreGold
Уровень 28
25 января 2016, 23:06
поддерживаю, тоже не прочь чтобы обьяснили.