2014-12-23 3 views
13

У меня есть круговая зависимость и java-конфиг. Хотя решение с помощью xml-конфигурации очень просто, я не могу разрешить его с помощью java-конфигурации без @Autowired. Фасоль:Весна. Разрешить циклическую зависимость с java-конфигурацией и без @Autowired

public class A { 
    private B b; 

    public B getB() { 
     return b; 
    } 

    public void setB(B b) { 
     this.b = b; 
    } 
} 

public class B { 
    private A a; 

    public A getA() { 
     return a; 
    } 

    public void setA(A a) { 
     this.a = a; 
    } 
} 

я пробовал это (я прочитал, что с @Bean аннотаций Spring не будет ссылаться на метод ссылается каждый раз, когда боб, но в данном случае это на самом деле был вызван все время):

@Configuration 
public class Config { 
    @Bean 
    public A a() { 
     A a = new A(); 
     a.setB(b()); 
     return a; 
    } 

    @Bean 
    public B b() { 
     B b = new B(); 
     b.setA(a()); 
     return b; 
    } 
} 

И это, с @Autowired полей классов конфигурации:

@Configuration 
public class Config { 
    @Autowired 
    A a; 
    @Autowired 
    B b; 

    @Bean 
    public A a() { 
     A a = new A(); 
     a.setB(b); 
     return a; 
    } 

    @Bean 
    public B b() { 
     B b = new B(); 
     b.setA(a); 
     return b; 
    } 
} 

Также я попробовал все выше @Lazy аннотацию. Не помогает. Но работает отлично, если я комментирую сеттеры A и B с @Autowired. Но я не хочу этого сейчас. Что я делаю неправильно и есть ли способ разрешить зависимость Circular в java-конфиге без использования @Autowired?

+0

Можете ли вы объяснить, но это не то, что я хочу прямо сейчас. Если это правильный инструмент для работы ... –

+0

@Sotirios Delimanolis мое приложение немного беспорядочно прямо сейчас, и я боюсь запутаться с зависимостями вокруг кода. Это не религиозно, и я люблю Autowired, но сейчас я бы предпочел сосредоточить бобы в одном файле конфигурации и управлять зависимостями руками. Также мне интересно, возможно ли это вообще. –

+0

На весеннем форуме была интересная дискуссия: http: //forum.spring.io/forum/spring-projects/container/127799-round-dependencies-with-autowired-in-java-configuration –

ответ

9

поведение вы хотите получить это следующие методы

A a = new A(); 
B b = new B(); 
a.setB(b); 
b.setA(a); 

@Bean не дают вам это. Они заканчиваются, чтобы предоставить экземпляр компонента.

Вам необходимо частично создать один из экземпляров, а затем завершить его инициализацию, когда вы создали другую.

@Configuration 
class Config { 
    @Bean 
    public A a() { 
     A a = new A(); 
     return a; 
    } 

    @Bean 
    public B b() { 
     B b = new B(); 
     A a = a(); 
     b.setA(a); 
     a.setB(b); 
     return b; 
    } 
} 

или

@Bean 
public B b(A a) { 
    B b = new B(); 
    b.setA(a); 
    a.setB(b); 
    return b; 
} 
+0

Метод 'b' мог бы' @ Autowire' bean 'a' (во избежание неявного вызова к методу 'a()' .Это не так? – wassgren

+0

@ wassgren Абсолютно. Хотя он не нуждается в явном '@ Autowired'. –

+0

Но это будет означать, что a и b получают неразделенные ссылки друг на друга. Аннотации не будут – flup

6

Другой подход с использованием @Autowired и @Component является использовать этот шаблон:

@Component 
class A { 
    private B b; 

    public B getB() { 
     return b; 
    } 

    public void setB(final B b) { 
     this.b = b; 
    } 
} 


@Component 
class B { 
    private final A a; 

    @Autowired 
    public B(final A a) { 
     this.a = a; 
     a.setB(this); 
    } 

    public A getA() { 
     return a; 
    } 
} 

Это устраняет необходимость в отдельном @Configuration -класса. Кроме того, метод setB может быть защищен от пакетов, если классы существуют в одном пакете, чтобы максимально сократить область охвата.

+0

Ваш ответ тоже полезен, мне грустно, что я не могу проголосовать, потому что я новичок. Спасибо. –

1

Я хочу добавить еще одно возможное решение для вашего кода. Вместо установки круговых зависимостей прямо в конфигурации:

@Configuration 
public class Config { 
    @Bean 
    public A a() { 
     A a = new A(); 
     a.setB(b()); 
     return a; 
    } 

    @Bean 
    public B b() { 
     B b = new B(); 
     b.setA(a()); 
     return b; 
    } 
} 

Вы также мог бы позволить весной сделать работу с силой @Autowired аннотации.

@Configuration 
public class Config { 
    @Bean 
    public A a() { 
     A a = new A(); 
     return a; 
    } 

    @Bean 
    public B b() { 
     B b = new B(); 
     return b; 
    } 
} 

public class A { 
    private B b; 

    @Autowired 
    public setB(B b) { this.b = b; } 
} 

public class B { 
    private A a; 

    @Autowired 
    public setA(A a) { this.a = a; } 
} 

Конечно, это не тривиальное от «чистого/чтения/понятной» точки зрения, потому что теперь ваша конфигурация смешивается в @Configuration и сам класс. Но поскольку круговые зависимости встречаются довольно редко, мы можем позволить себе взломать.

+0

Суть в том, чтобы сделать это ** без ** '@ Autowired' (хотя не спрашивайте меня, почему) –

+0

О, я вижу. В любом случае, пусть это будет здесь. Спасибо. –

Смежные вопросы