Позвольте мне дать вам другую перспективу.
Скажем, есть еще один компонент AnotherBeanConsumer
, которому также требуется simpleBean
.Simple Bean имеет область действия Singleton :
@Configuration
public class Config {
@Bean
public SimpleBean simpleBean() {
return new SimpleBean();
}
@Bean
public SimpleBeanConsumer simpleBeanConsumer() {
return new SimpleBeanConsumer(simpleBean());
}
@Bean
public AnotherBeanConsumer anotherBeanConsumer() {
return new AnotherBeanConsumer(simpleBean());
}
}
Теперь вопрос состоит в том, как возможно, что два вызова simpleBean()
, сделанные из различных методов simpleBeanConsumer
и anotherBeanConsumer
, возвращаюттот же самый экземпляр простого бина (поскольку он, очевидно, является синглтоном)?
IMO (и отказ от ответственности, я не связан с Spring или чем-то подобным), это главная причина создания прокси, которые обертывают конфигурации.
Теперь, действительно, у Spring AOP есть ограничение вызова методов, как вы и заявили, однако кто сказал, что подпружиненный Spring использует AOP пружины?Инструментарий байт-кода, выполняемый на гораздо более низких уровнях, не имеет таких ограничений.В конце концов, создание прокси означает: «создайте прокси-объект, который будет иметь тот же интерфейс, но изменит поведение», верно?
Например, если вы используете CGLIB, который использует наследование, вы можете создать прокси из конфигурацииэто выглядит примерно так (схематично):
class CGLIB_GENERATED_PROXY extends Config {
private Map<String, Object> singletonBeans;
public SimpleBean simpleBean() {
String name = getNameFromMethodNameMaybePrecached();
if(singletonBeans.get(name) != null) {
return singletonBeans.get(name);
}
else {
SimpleBean bean = super.simpleBean();
singletonBeans.put(name, bean);
return bean;
}
}
....
}
Конечно, это всего лишь схематическое изображение, в реальной жизни есть контекст приложения, который в основном обеспечивает такой доступ к карте, но вы понимаете, в чем дело.
Если этого недостаточно, то существуют еще более сложные фреймворки, которые пружина должна использовать для загрузки конфигурации (например, ASM) ...
Вот пример: есливы используете @ConditionalOnClass(A.class)
и класс на самом деле не существует во время выполнения, как Spring может загрузить байт-код конфигурации, которая использует эту конфигурацию, и не дать сбой чему-то вроде NoClassDefFoundException
?
Я хочу сказать, что онвыходит далеко за пределы весеннего АОП и имеет свои причуды:)
Сказав это, ничего из того, что я описал выше, не требуетРеальные компоненты должны быть всегда в прокси любого вида.Таким образом, в самом тривиальном случае, когда SimpleBean
сам по себе не имеет некоторых аннотаций, требующих генерации прокси (например, @Cached
, @Transactional
и т. Д.), Spring не будет переносить объект этого типа, и вы 'получите простой SimpleBean
объект.