Spring自动装配(三)-注入底层Bean

Aware

Aware是一个接口,通常继承了该接口的都可以获得Spring提供的相关信息。

这里简单介绍常用的子接口。

ApplicationContextAware

使用ApplicationContextAware可以获得容器上下文

使用

实现ApplicationContextAware接口

@Service
public class UserService implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

这样就获得了容器上下文。

EmbeddedValueResolverAware

EmbeddedValueResolverAware用于获得字符串解析器

使用
@Component
public class User implements EmbeddedValueResolverAware {

    private StringValueResolver resolver;

    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.resolver = resolver;
    }
}

这样就获取到了字符串解析器。
字符串解析器有什么用?

@Component
public class User implements EmbeddedValueResolverAware {

    private StringValueResolver resolver;

    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.resolver = resolver;
    }

    public String getOsName() {
        return resolver.resolveStringValue("${os.name}");
    }
}
public class Application {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        User user = annotationConfigApplicationContext.getBean(User.class);
        System.out.println(user.getOsName());
       }
}

输出内容
在这里插入图片描述
作用就是解析${},去Environment中获取数据。Environment不知道是什么的朋友可以看看我前面的文章有介绍到。

BeanNameAware

BeanNameAware可以获得BeanName

使用

实现BeanNameAware接口

@Component
public class User implements BeanNameAware {
    
    private String beanName;

    public String getBeanName() {
        return beanName;
    }

    public void setBeanName(String name) {
        beanName = name;
    }
}

beanName的值就是当前bean的name。

Spring如何实现的?

以BeanNameAware为例子,从Spring初始化容器开始说起:

  1. 在构建AnnotationConfigApplicationContext会调用refresh()方法

    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    		this();
    		register(annotatedClasses);
    		refresh();
    }
    
  2. 在refresh()方法中调用了finishBeanFactoryInitialization实例化所有剩余的非延迟加载的单例Bean。

    public void refresh() throws BeansException, IllegalStateException {
    		synchronized (this.startupShutdownMonitor) {
    			// Prepare this context for refreshing.
    			prepareRefresh();
    
    			// Tell the subclass to refresh the internal bean factory.
    			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
    			// Prepare the bean factory for use in this context.
    			prepareBeanFactory(beanFactory);
    
    			try {
    				// Allows post-processing of the bean factory in context subclasses.
    				postProcessBeanFactory(beanFactory);
    
    				// Invoke factory processors registered as beans in the context.
    				invokeBeanFactoryPostProcessors(beanFactory);
    
    				// Register bean processors that intercept bean creation.
    				registerBeanPostProcessors(beanFactory);
    
    				// Initialize message source for this context.
    				initMessageSource();
    
    				// Initialize event multicaster for this context.
    				initApplicationEventMulticaster();
    
    				// Initialize other special beans in specific context subclasses.
    				onRefresh();
    
    				// Check for listener beans and register them.
    				registerListeners();
    
    				// Instantiate all remaining (non-lazy-init) singletons.
    				finishBeanFactoryInitialization(beanFactory);
    
    				// Last step: publish corresponding event.
    				finishRefresh();
    			}
    			//提高可读性省略不必要的代码
    		}
    	}
    
  3. 在finishBeanFactoryInitialization中调用beanFactory.preInstantiateSingletons()

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    		// Initialize conversion service for this context.
    		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
    				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
    			beanFactory.setConversionService(
    					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    		}
    
    		// Register a default embedded value resolver if no bean post-processor
    		// (such as a PropertyPlaceholderConfigurer bean) registered any before:
    		// at this point, primarily for resolution in annotation attribute values.
    		if (!beanFactory.hasEmbeddedValueResolver()) {
    			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    		}
    
    		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    		for (String weaverAwareName : weaverAwareNames) {
    			getBean(weaverAwareName);
    		}
    
    		// Stop using the temporary ClassLoader for type matching.
    		beanFactory.setTempClassLoader(null);
    
    		// Allow for caching all bean definition metadata, not expecting further changes.
    		beanFactory.freezeConfiguration();
    
    		// Instantiate all remaining (non-lazy-init) singletons.
    		beanFactory.preInstantiateSingletons();
    	}
    

    途中经过各种步骤
    然后在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean方法中调用了initializeBean。在initializeBean再调用了invokeAwareMethods方法

    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    		if (System.getSecurityManager() != null) {
    			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    				invokeAwareMethods(beanName, bean);
    				return null;
    			}, getAccessControlContext());
    		}
    		else {
    			invokeAwareMethods(beanName, bean);
    		}
    
    		Object wrappedBean = bean;
    		if (mbd == null || !mbd.isSynthetic()) {
    			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    		}
    
    		try {
    			invokeInitMethods(beanName, wrappedBean, mbd);
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(
    					(mbd != null ? mbd.getResourceDescription() : null),
    					beanName, "Invocation of init method failed", ex);
    		}
    		if (mbd == null || !mbd.isSynthetic()) {
    			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    		}
    
    		return wrappedBean;
    	}
    
  4. 重点来了,在invokeAwareMethods中可以看到判断当前bean是否是BeanNameAware,如果是的话就调用setBeanName把beanName传递过去。

	private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

这里主要是介绍了下大概流程,具体详细过程,感兴趣的朋友可以具体看看Spring源码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值