Я попытаюсь объяснить
, если конфиг помечен как компонент, то Spring не создает прокси-класс этого конфига
Контейнер Spring создает прокси для бина только если это требуется, как для любой специальной обработки для компонента, например: AOP, Transaction Management. Я объяснил это для другого SO вопроса здесь , пожалуйста, go через раздел A2 ответа, если вы заинтересованы.
Так, например, компонент класса Conf
будет прокси, если класс аннотирован @Transactional
.
все сконфигурированные компоненты внутри этого класса рассматриваются как простой метод звонки
Не правильно. Все самостоятельные вызовы или внутренние вызовы методов в режиме Lite являются простыми вызовами методов в отличие от специальной обработки внутри класса, помеченного @Configuration
. В аннотированном классе @Configuration
несколько вызовов аннотированного метода @Bean
возвращают один и тот же экземпляр компонента.
Из документации @ Bean
В отличие от семантики для методов bean-компонентов в классах @Configuration, «ссылки между компонентами» не поддерживаются в облегченном режиме. Вместо этого, когда один @ Bean-метод вызывает другой @ Bean-метод в облегченном режиме, это стандартный вызов метода Java; Spring не перехватывает вызов через прокси-сервер CGLIB. Это аналогично вызовам метода inter-@Transactional, когда в режиме прокси Spring не перехватывает вызов - Spring делает это только в режиме AspectJ.
Итак, наблюдение, что
Spring создал прокси для bean-компонента, аннотированного как @Transactional и настроенного внутри класса @Component
, как и ожидалось по причинам
- Класс, аннотированный
@Transactional
, нуждается в проксировании - Класс, помеченный
@Component
, в этом примере не требует специальной обработки
Я изменил ваш пример, чтобы объяснить это лучше
Заметные изменения
- Аннотируемый
@Component
аннотированный класс с @Transactional
для объяснения проксирования. - Добавление класса
@Configuration
для объяснения поддержки 'межбиновых ссылок' - Нет
@Transactional
для ConfigurationBean.init()
метода объяснения прокси.
Код
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@SpringBootApplication
public class TranslatorApplication implements CommandLineRunner {
@Autowired
ComponentBean beanOne;
@Autowired
ComponentBean beanTwo;
@Autowired
ComponentConf conf;
@Autowired
ConfigurationBean beanThree;
@Autowired
ConfigurationBean beanFour;
@Autowired
ConfigurationConf config;
public static void main(final String[] args) {
SpringApplication.run(TranslatorApplication.class, args);
}
@Override
public final void run(final String... args) {
System.out.println(conf+" : "+conf.getClass().getSimpleName());
System.out.println(beanOne+" : "+beanOne.getClass().getSimpleName());
System.out.println(beanTwo+" : "+beanTwo.getClass().getSimpleName());
System.out.println(config+" : "+config.getClass().getSimpleName());
System.out.println(beanThree+" : "+beanThree.getClass().getSimpleName());
System.out.println(beanFour+" : "+ beanFour.getClass().getSimpleName());
}
interface ComponentConfIntf{}
@Component
@Transactional
static class ComponentConf{
@Bean
public ComponentBean beanOne() {
return new ComponentBean();
}
@Bean
public ComponentBean beanTwo() {
return beanOne();
}
}
static class ComponentBean {
@Transactional
public void init() {
}
}
@Configuration
static class ConfigurationConf {
@Bean
public ConfigurationBean beanThree() {
return new ConfigurationBean();
}
@Bean
public ConfigurationBean beanFour() {
return beanThree();
}
}
static class ConfigurationBean {
public void init() {
}
}
}
Печать
rg.xx.xx.TranslatorApplication$ComponentConf@8a589a2 : TranslatorApplication$ComponentConf$$EnhancerBySpringCGLIB$$e204f764
rg.xx.xx.TranslatorApplication$ComponentBean@c65a5ef : TranslatorApplication$ComponentBean$$EnhancerBySpringCGLIB$$d3d05c88
rg.xx.xx.TranslatorApplication$ComponentBean@6b5176f2 : TranslatorApplication$ComponentBean$$EnhancerBySpringCGLIB$$d3d05c88
rg.xx.xx.TranslatorApplication$ConfigurationConf$$EnhancerBySpringCGLIB$$9369a982@b672aa8 : TranslatorApplication$ConfigurationConf$$EnhancerBySpringCGLIB$$9369a982
rg.xx.xx.TranslatorApplication$ConfigurationBean@2fab4aff : ConfigurationBean
rg.xx.xx.TranslatorApplication$ConfigurationBean@2fab4aff : ConfigurationBean
Обратите внимание, что
ComponentConf
bean-компонент прокси. ComponentBean
r Возврат двух разных экземпляров бина из-за режима Lite . ConfigurationBean
возвращает один и тот же экземпляр. ConfigurationBean
экземпляры не проксируются.
Отличный ответ от @kriegaex о работе класса @Configuration
. Читайте.
Надеюсь, это поможет.