Configuration 的 proxyBeanMethods 属性与 Bean 方法
@Configuration 的 proxyBeanMethods 属性与 @Bean 方法
@Configuration 注解所标注的配置类中,我们常常使用 @Bean 标注来方法向 IoC 容器中注册组件。
@Configuration 的 proxyBeanMethods 属性用来控制是否对 @Bean 方法进行代理。
如果
proxyBeanMethods = true,那么 Spring 会将@Configuration所标注的配置类作为目标类来生成相应的代理类,最后将代理类注册到容器中。类中的
@Bean方法均被加上一层代理,此时向 IoC 容器中注册组件的具体逻辑,是在@Bean方法的代理的后置增强中完成。无论是 Spring 为了注册组件去调用
@Bean方法,还是用户代码中去主动调用@Bean方法,所调用的都是代理方法,需要经过增强代码处理。前置增强:尝试从 IoC 容器中获取类型为
@Bean方法返回值类型的对象,如果能够获取到,则直接返回 IoC 容器中的相应对象,如果获取不到执行目标方法。目标方法:就是我们自己编写的
@Bean方法中的内容,它负责创建一个新对象然后返回后置增强:获取到目标方法的返回值以后,将该新对象注册到 IoC 容器中。
如果
proxyBeanMethods = false,那么 Spring 会将@Configuration所标注的配置类直接注册到容器中。类中的
@Bean方法此时无代理,此时向 IoC 容器中注册组件的具体逻辑,是在 Spring 中另外一块代码来完成。无论是 Spring 为了注册组件去调用
@Bean方法,还是用户代码中去主动调用@Bean方法,都是直接创建新对象返回。只不过 Spring 为了注册去调用的话,得到返回值以后还需要将该返回值注册到 IoC 容器中。
proxyBeanMethods = true + 组件依赖的情况下,Spring 调用 @Bean 方法进行组件注册的流程
1 |
|
Spring 会顺序扫描 @Configuration 所标注的 MyConfig 类中的 @Bean 方法并进行调用,所以 Spring 会先调用 user01(),然后再调用 tomcatPet()。
- Spring 调用
user01()来进行组件注册,该方法已被代理,代理发现 IoC 容器中目前还没有User对象,所以接下来会执行目标user01()方法 - 执行目标
user01()方法,在内部新创建了一个User对象命名为zhangsan,然后在执行zhangsan.setPet(tomcatPet())时,转而去调用tomcatPet()方法。 tomcatPet()方法也是@Bean方法,因此先经过代理,代理发现,IoC 容器中目前还没有Pet对象,所以接下来会执行目标tomcatPet()方法- 执行目标
tomcatPet()方法,创建了一个Pet对象并返回,代理的后置增强将该新Pet对象注册到 IoC 容器中,然后继续返回。 zhangsan.setPet(tomcatPet())将返回的Pet对象设置到zhangsan的属性中,然后user01()目标方法执行结束并返回一个User对象,代理的后置增强,将该新User对象注册到 IoC 容器中。- Spring 调用
tomcatPet()来进行组件注册,该方法已被代理,代理发现 IoC 容器中已存在Pet对象,因此直接返回。
proxyBeanMethods = false + 组件依赖的情况下,Spring 调用 @Bean 方法进行组件注册的流程
1 |
|
Spring 会顺序扫描 @Configuration 所标注的 MyConfig 类中的 @Bean 方法并进行调用,所以 Spring 会先调用 user01(),然后再调用 tomcatPet()。
- Spring 调用
user01()来进行组件注册,方法无代理可直接执行,方法内部创建了一个User对象并命名为zhangsan,然后在执行zhangsan.setPet(tomcatPet())时,转而去调用tomcatPet()方法。 tomcatPet()方法无代理可直接执行,创建一个Pet对象并返回。zhangsan.setPet(tomcatPet())将返回的Pet对象设置到zhangsan的属性中,然后user01()方法执行结束并返回一个User对象。- Spring 将返回的
User对象注册到 IoC 容器中。 - Spring 调用
tomcatPet()来进行组件注册,方法无代理可直接执行,方法内部创建了一个Pet对象并返回。 - Spring 将返回的
Pet对象注册到 IoC 容器中。