@Configuation 这个注解相信大家都使用过,那么它和普通的@Component的派生注解有什么不同呢。
先贴出一个最后总结的流程图
@Configuration大体逻辑流程
我们先随便百度还是谷狗一些内容。都谈到了@Configuration中@Bean可以在类内部调用注入bean的方法而不会产生两个实例,会保证单例。那么来看看这个逻辑
@Configuration
// 默认boolean proxyBeanMethods() default true 即当前@Configuation注解下的类会被设置为代理类
public class YhrConfigTest {
@Bean
// proxyBeanMethods -> true 会代理 @Bean注解的方法,保证只会真正调用一次,后面的调用会直接从 spring ioc中取
public PulsarTest init() {
return new PulsarTest();
}
@Bean
public TestBean initService() {
// 默认的proxyBeanMethods -> true 支持这种类内部的重复调用 @Bean注解的方法获取bean,而又保证单例,通过 cglib的动代来实现
PulsarTest pulsarTest = init();
return new TestBean(pulsarTest);
}
}
这种使用方式被视为ConfigurationClassUtils#CONFIGURATION_CLASS_FULL 即full 模式,另一种为lite模式不存在动态代理对象,为直接的@Configuration注解下的bean,区别就是full模式由动代进行了一层拦截处理。现在很多源码和官方推荐使用lite模式,即可以看到很多 proxyBeanMethods=false的代码,如果不适用到代理提供的特性尽量使用lite模式
我们来看看@Configuration 代理实现的具体逻辑
先从代理方法入手
- 我们跟踪上述代码中的另一个@Bean中的init()方法
class ConfigurationClassEnhancer {
// 省略部分代码...
// 这里一看就是 生成 cglib动态代理的方法。传入目标configClass和classLoader,一会可以从这里debug看 spring启动时当前方法外部逻辑
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Ignoring request to enhance %s as it has " +
"already been enhanced. This usually indicates that more than one " +
"ConfigurationClassPostProcessor has been registered (e.g. via " +
"<context:annotation-config>). This is harmless, but you may " +
"want check your configuration and remove one CCPP if possible",
configClass.getName()));
}
return configClass;
}
// 这里生成了 动态代理 class
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
if (logger.isTraceEnabled()) {
logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
configClass.getName(), enhancedClass.getName()));
}
return enhancedClass;
}
/**
* Creates a new CGLIB {@link Enhancer} instance.
*/
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(configSuperClass);
// 标记 cglib动态代理子类 方便从接口维度管理
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
enhancer.setUseFactory(false);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
// 字节码生成策略
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
// 动态代理拦截后 cglib的回调
enhancer.setCallbackFilter(CALLBACK_FILTER);
//同上 动态代理 cglib的回调,可以设置多个回调拦截,通过返回下表来选择指定的拦截实现生成,当前类中包含一个 无拦截生成逻辑。
org.springframework.cglib.proxy.NoOp,都实现了org.springframework.cglib.proxy.CallBack接口,如果需要真正的拦截,需要再实现MethodInterceptor 接口和上述类同包。也可以看看这个实现类中spring做了哪些拦截逻辑,结合CallbackFilter#accept方法,当前filter都会选中通过accept指定的Callback
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;
}
// 使用 spring的 cglib封装创建 class对象
private Class<?> createClass(Enhancer enhancer) {
Class<?> subclass = enhancer.createClass();
// Registering callbacks statically (as opposed to thread-local)
// is critical for usage in an OSGi environment (SPR-5932)...
Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
return subclass;
}
// config的动态代理类 接口标记
public interface EnhancedConfiguration extends BeanFactoryAware {
}
//
private interface ConditionalCallback extends Callback {
// cglig 回调拦截的适配方法。哪些方法会被适配到拦截
boolean isMatch(Method candidateMethod);
}
private static class ConditionalCallbackFilter implements CallbackFilter {
// cglib 回调拦截 列表 只有三种,在当前类的成员变量中
private final Callback[] callbacks;
// 拦截方法的class 对象
private final Class<?>[] callbackTypes;
public ConditionalCallbackFilter(Callback[] callbacks) {
this.callbacks = callbacks;
this.callbackTypes = new Class<?>[callbacks.length];
for (int i = 0; i < callbacks.length; i++) {
this.callbackTypes[i] = callbacks[i].getClass();
}
}
// 当前方法是让具体的每个方法选择 callBack具体哪个实现,因为Spring的cglib动态代理对象可以放入多个 CallBack拦截实现具体可以看org.springframework.cglib.proxy.Enhancer#emitMethods
@Override
public int accept(Method method) {
// 这里实际是当前动态代理对象,符合当前
for (int i = 0; i < this.callbacks.length; i++) {
Callback callback = this.callbacks[i];
if (!(callback instanceof ConditionalCallback) || ((ConditionalCallback) callback).isMatch(method)) {
// 当前method适用于那种 CallBack拦截逻辑(可能利用NoOp类不进行拦截)
return i;
}
}
throw new IllegalStateException("No callback available for method " + method.getName());
}
public Class<?>[] getCallbackTypes() {
return this.callbackTypes;
}
}
// 字节码生成策略,这个是spring提供的cglib实现的逻辑
private static class BeanFactoryAwareGeneratorStrategy extends
ClassLoaderAwareGeneratorStrategy {
public BeanFactoryAwareGeneratorStrategy(@Nullable ClassLoader classLoader) {
super(classLoader);
}
@Override
protected ClassGenerator transform(ClassGenerator cg) throws Exception {
ClassEmitterTransformer transformer = new ClassEmitterTransformer() {
@Override
public void end_class() {
declare_field(Constants.ACC_PUBLIC, BEAN_FACTORY_FIELD, Type.getType(BeanFactory.class), null);
super.end_class();
}
};
return new TransformingClassGenerator(cg, transformer);
}
}
// 要拦截setBeanFactory方法的代理方法,因为所有bean都会自动进行BeanFactoryAware#setBeanFactory钩子的回调,这里是拦截这个回调。如果当前类实现了BeanFactoryAware接口则返回父类的原始调用,不使用当前代理调用
private static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback {
@Override
@Nullable
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Field field = ReflectionUtils.findField(obj.getClass(), BEAN_FACTORY_FIELD);
Assert.state(field != null, "Unable to find generated BeanFactory field");
// 生成的代理类会通过这个setBeanFactory方法的代理进行BeanFactory注入,将代理类和正常的bean一样将其与beanFactory自动连接起来
field.set(obj, args[0]);
// Does the actual (non-CGLIB) superclass implement BeanFactoryAware?
// If so, call its setBeanFactory() method. If not, just exit.
if (BeanFactoryAware.class.isAssignableFrom(ClassUtils.getUserClass(obj.getClass().getSuperclass()))) {
return proxy.invokeSuper(obj, args);
}
return null;
}
// 适配器,当前方法是否会被代理。
@Override
public boolean isMatch(Method candidateMethod) {
return isSetBeanFactory(candidateMethod);
}
// 从这个适配可以看处只代理了setBeanFactory(BeanFactory beanFactory)并且只有一个参数的方法
public static boolean isSetBeanFactory(Method candidateMethod) {
return (candidateMethod.getName().equals("setBeanFactory") &&
candidateMethod.getParameterCount() == 1 &&
BeanFactory.class == candidateMethod.getParameterTypes()[0] &&
BeanFactoryAware.class.isAssignableFrom(candidateMethod.getDeclaringClass()));
}
}
// 要代理 @Bean注解的方法
private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
// 获取bean工厂
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
// 获取 @Bean方法指定的 bean名称
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
// 除了默认单例的 其他作用域的bean
// Determine whether this bean is a scoped-proxy
if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
beanName = scopedBeanName;
}
}
// To handle the case of an inter-bean method reference, we must explicitly check the
// container for already cached instances.
// First, check to see if the requested bean is a FactoryBean. If so, create a subclass
// proxy that intercepts calls to getObject() and returns any cached bean instance.
// This ensures that the semantics of calling a FactoryBean from within @Bean methods
// is the same as that of referring to a FactoryBean within XML. See SPR-6602.
//*********这里是重点!!!这里就是上面@Bean方法和当前@Configuration类中的方法复用了@Bean方法,会看如果已经在容器中含有了,不会再次初始化,前提是@Configuration使用默认,那么当前类就是一个cglib代理,如果不是代理不会进入当前方法拦截噢。
if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
factoryContainsBean(beanFactory, beanName)) {
// 如果已经在容器中,并且不是新建中的中间状态会进入当前代码块
Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
if (factoryBean instanceof ScopedProxyFactoryBean) {
// 如果是除了默认的 单例模式的bean,其他作用域都不做处理,会进行多次初始化
// Scoped proxy factory beans are a special case and should not be further proxied
}
else {
// It is a candidate FactoryBean - go ahead with enhancement
// 直接返回 cglib动态代理bean
return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
}
}
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
//兼容 groovy可能出现的 动态bean加载,当前factory正在调用getBean实例化当前bean则需要调用原始bean中的方法实现
// The factory is calling the bean method in order to instantiate and register the bean
// (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
// create the bean instance.
if (logger.isInfoEnabled() &&
BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
"assignable to Spring's BeanFactoryPostProcessor interface. This will " +
"result in a failure to process annotations such as @Autowired, " +
"@Resource and @PostConstruct within the method's declaring " +
"@Configuration class. Add the 'static' modifier to this method to avoid " +
"these container lifecycle issues; see @Bean javadoc for complete details.",
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
}
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}
return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}
// 当前方法一定是通过 @Confiuration类中full模式被代理的@Bean方法
//相当于用户直接使用方法获取bean
private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
ConfigurableBeanFactory beanFactory, String beanName) {
// The user (i.e. not the factory) is requesting this bean through a call to
// the bean method, direct or indirect. The bean may have already been marked
// as 'in creation' in certain autowiring scenarios; if so, temporarily set
// the in-creation status to false in order to avoid an exception.
boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
try {
if (alreadyInCreation) {
// 如果是创建中,则先设置为false,防止异常情况
beanFactory.setCurrentlyInCreation(beanName, false);
}
// 处理@Bean 方法中通过参数 @Autowired其他bean
boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
// 如果@Bean返回的bean是单例,并且通过@Bean方法注入了其他bean
if (useArgs && beanFactory.isSingleton(beanName)) {
// Stubbed null arguments just for reference purposes,
// expecting them to be autowired for regular singleton references?
// A safe assumption since @Bean singleton arguments cannot be optional...
for (Object arg : beanMethodArgs) {
if (arg == null) {
// 如果其他bean有没有注入成功的设置 参数为false
useArgs = false;
break;
}
}
}
// 如果参数都注入则一起通过bean工厂获取,如果有的没注入成功则直接获取当前bean
Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
beanFactory.getBean(beanName));
// 如果@Bean返回的 bean type 和当前使用beanName从工厂获取的bean不一致
if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
// Detect package-protected NullBean instance through equals(null) check
// 如果是没有获取到bean 不做什么,后续返回null
if (beanInstance.equals(null)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("@Bean method %s.%s called as bean reference " +
"for type [%s] returned null bean; resolving to null value.",
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
beanMethod.getReturnType().getName()));
}
beanInstance = null;
}
else {
String msg = String.format("@Bean method %s.%s called as bean reference " +
"for type [%s] but overridden by non-compatible bean instance of type [%s].",
beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
beanMethod.getReturnType().getName(), beanInstance.getClass().getName());
try {
// 尝试从 工厂获取 BeanDefinition
BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription();
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore - simply no detailed message then.
}
throw new IllegalStateException(msg);
}
}
// 从threadLocal查看当前 工厂正在调用的 工厂方法
Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
if (currentlyInvoked != null) {
// 当前工厂在运行 方法不为空时
String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
// 为当前@Bean 方法的bean 注入这个正在调用工厂方法bean作为依赖bean注册,这里不明白,后续会仔细研究一下 beanFactory.registerDependentBean(beanName, outerBeanName);
}
return beanInstance;
}
finally {
if (alreadyInCreation) {
// 刚才置为 false的状态重新置回 beanFactory.setCurrentlyInCreation(beanName, true);
}
}
}
@Override
public boolean isMatch(Method candidateMethod) {
// 适配器,当前拦截方法为了拦截@Bean的方法,还要排除 SetBeanFactory,并且@Bean的方法不可以返回 Object噢
return (candidateMethod.getDeclaringClass() != Object.class &&
!BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&
BeanAnnotationHelper.isBeanAnnotated(candidateMethod));
}
// 省略部分代码...
上面跟踪了整体@Configuration full模式的 setBeanFactory方法拦截
以及对@Bean注解的方法拦截逻辑,通过适配器以及spring的cglib动态代理的组合实现了重复调用@Bean注解的方法只初始化一次bean
-
接下来看创建bean的流程。通过逆向来看
生成代理的类
一看,是我们很熟悉的BeanPostProcessor钩子接口
// 先看看这个类实现了哪些钩子, 对于bean操作的钩子就是BeanDefinitionRegistryPostProcessor 含有两个维度的 bean钩子,一个是BeanFactoryPostProcessor#postProcessBeanFactory 工厂的钩子一个是bean注册器的钩子,这两个钩子是重点
BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, ApplicationStartupAware, BeanClassLoaderAware, EnvironmentAware
那么我们先从 beanFactory钩子来看
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
// 如果当前没有BeanDefinitionRegistryPostProcessor 当前@Configuration的bean工厂没有到达钩子的调用时机,是不允许去创建代理的,需要再去调用BeanDefinitionRegistryPostProcessor 的钩子,实际是再去重新注入一遍@Configuration的bean
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
// @Configuration full 模式进行代理
enhanceConfigurationClasses(beanFactory);
// 这是动态加入一个新得钩子先具体看看逻辑
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
我们先看ImportAwareBeanPostProcessor这个内部类逻辑,然后再看enhanceConfigurationClasses方法生成代理,然后看processConfigBeanDefinitions
private static class ImportAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
private final BeanFactory beanFactory;
public ImportAwareBeanPostProcessor(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public PropertyValues postProcessProperties(@Nullable PropertyValues pvs, Object bean, String beanName) {
// Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor's
// postProcessProperties method attempts to autowire other configuration beans.
// 这是我们最初看到的 生成的代理类标记的接口,在这里对它setBeanFactory钩子调用, 这就找到了我们动态生成的cglib代理类是如何调用setBeanFactory钩子的,这里会进行调用同时代理会拦截setBeanFactory方法将成员变量的BeanFactory传入赋值
if (bean instanceof EnhancedConfiguration) {
((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory);
}
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (bean instanceof ImportAware) {
// 如果这个@Configuration类是full模式,并且
ImportRegistry ir = this.beanFactory.getBean(IMPORT_REGISTRY_BEAN_NAME, ImportRegistry.class);
AnnotationMetadata importingClass = ir.getImportingClassFor(ClassUtils.getUserClass(bean).getName());
if (importingClass != null) {
((ImportAware) bean).setImportMetadata(importingClass);
}
}
return bean;
}
}
下面再来看看 enhanceConfigurationClasses方法的逻辑
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
StartupStep enhanceConfigClasses = this.applicationStartup.start("spring.context.config-classes.enhance");
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
// 获取beanDefinition
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
// 获取configurationClass 的属性
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
AnnotationMetadata annotationMetadata = null;
MethodMetadata methodMetadata = null;
// 如果是注解注入bean的获取注解属性,其实现在都不使用xml,都是使用@Component及其派生
if (beanDef instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDef;
annotationMetadata = annotatedBeanDefinition.getMetadata();
methodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();
}
// 使用注解@Configuation,因为可以获取到@Configuration特有的属性并且是注解注入bean则一定是 @Configuration
if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
// Configuration class (full or lite) or a configuration-derived @Bean method
// -> eagerly resolve bean class at this point, unless it's a 'lite' configuration
// or component class without @Bean methods.
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
if (!abd.hasBeanClass()) {
// 通过@Configuration的proxyBeanMethods属性的值和
boolean liteConfigurationCandidateWithoutBeanMethods =
(ConfigurationClassUtils.CONFIGURATION_CLASS_LITE.equals(configClassAttr) &&
annotationMetadata != null && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata));
if (!liteConfigurationCandidateWithoutBeanMethods) {
try {
// 如果是 full 模式放入 beanClassLoader
abd.resolveBeanClass(this.beanClassLoader);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}
}
if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
}
else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
logger.info("Cannot enhance @Configuration bean definition '" + beanName +
"' since its singleton instance has been created too early. The typical cause " +
"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
"return type: Consider declaring such methods as 'static'.");
}
// 将full模式的 @Configuration 收集
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
if (configBeanDefs.isEmpty() || NativeDetector.inNativeImage()) {
// 没有full模式直接返回
// nothing to enhance -> return immediately
enhanceConfigClasses.end();
return;
}
// 开始通过 spring aop包下封装的cglib动态代理对@Configuration进行代理
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
// If a @Configuration class gets proxied, always proxy the target class
// 这又是老朋友了, 将@EnableAspectJAutoProxy的proxyTargetClass属性设置为true,就是标记当前类使用cglib代理,默认false使用jdk基于接口的代理
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// Set enhanced subclass of the user-specified bean class
Class<?> configClass = beanDef.getBeanClass();
// 又见到新朋友了,这里是调用上面代码的ConfigurationClassEnhancer#enhance生成代理class对象
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
// 将 bean的class替换为动态代理子类
beanDef.setBeanClass(enhancedClass);
}
}
enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();
}
然后processConfigBeanDefinitions 方法
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
// 显示已经进入到注册器的bean 全部取出来遍历
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
// 如果是当前ConfigurationClassPostProcessor 这个bean忽略
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
// 如果是 @Configuration 的注入的bean 则收集,这个方法不跟进去了,这里收集@Configuration时会过滤掉BeanFactoryPostProcessor,BeanPostProcessor,AopInfrastructureBean,EventListenerFactory子类,这里不太明白。。。以后多看看spring的逻辑或许会懂
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// 这里看到了 如果发现@Configuration类会将其解析
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 用于收集的容器
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
// 一个一个bean来解析 @Configuration 并验证
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
// 防止重复解析,将已经处理过的 移除
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 这里是 注入 @Bean的 bean噢,也就是@Bean的实现就是通过这个方法,当前方法不停的检测是否有新的 @Configuration注入然后到这里进行@Bean的注入
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
candidates.clear();
// 如果当前程序在刚进入方法,到当前代码行有新的bean装载,需要处理
if (registry.getBeanDefinitionCount() > candidateNames.length) {
// 获取新得 bean 包含旧的
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
// 将已经装载的 @Configuration bean放入上面的set容器
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
// 遍历所有新的bean 包含已经装载的
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
// 如果是新的bean
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
// 如果是 @Configuration 的bean同时是未装载过的收集
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
// 旧的全部 bean names 引用换成新的
candidateNames = newCandidateNames;
}
}
// 一直发现有新的 @Configuration 装载到 bean注册器才跳出,那么就可以解释方法调用方是在未发现已经注册的对应 @Configuration到这个方法再进行处理,并且这个注册器的bean是要缓存到当前类对象中通过postProcessBeanDefinitionRegistry 也不停的调用当前方法
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
// 支持 ImportAware
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
//这里是为了支持@Configuration类上的@Import注入
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
// 产生新的载入动作 清除缓存
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
总结
- BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry通过注册器来对当前beanFactory的bean进行整理操作
- BeanFactoryPostProcessor#postProcessBeanFactory 后于上面方法的钩子时机对已经注册的@Configuration类进行代理并考虑懒加载
- 使用spring-aop的cglib动态代理的封装对指定 setBeanFactory和@Bean注解到的方法进行代理拦截
- 通过InstantiationAwareBeanPostProcessor#postProcessProperties和postProcessBeforeInitialization方法对生成的代理类进ImportAware和setBeanFactory自动连接
- 使用cglib拦截指定的方法进行逻辑操作,当然我们就拦截了setBeanFactory和 @Bean注解的方法进行操作