10ConfigurationClassPostProcessor
ConfigurationClassPostProcessor
- 处理configuration的后置处理器
- 实现了BeanDefinitionRegistryPostProcessor接口
postProcessBeanDefinitionRegistry

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//获取到beanDefinition的名称列表
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
//根据beanName获取beanDefinition
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
//如果属性不为空,则表示已经处理过了
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
//判断有没有加Configuration,Import等注解,如果加了还要判断有没有实现Order接口,
// 然后BeanDefinition设置Attribute,CONFIGURATION_CLASS_ATTRIBUTE
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
//configCandidates是所有加了注解的
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
//根据@Order排序
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();
}
// 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 {
// 解析配置类,在此处会解析配置类上的注解(ComponentScan扫描出的类,@Import注册的类,以及@Bean方法定义的类)
// 注意:这一步只会将加了@Configuration注解以及通过@ComponentScan注解扫描的类才会加入到BeanDefinitionMap中
// 通过其他注解(例如@Import、@Bean)的方式,在parse()方法这一步并不会将其解析为BeanDefinition放入到BeanDefinitionMap中,
// 而是先解析成ConfigurationClass类
// 真正放入到map中是在下面的this.reader.loadBeanDefinitions()方法中实现的
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());
}
// 将上一步parser解析出的ConfigurationClass类加载成BeanDefinition
// 实际上经过上一步的parse()后,解析出来的bean已经放入到BeanDefinition中了,但是由于这些bean可能会引入新的bean,
// 例如实现了ImportBeanDefinitionRegistrar或者ImportSelector接口的bean,或者bean中存在被@Bean注解的方法
// 因此需要执行一次loadBeanDefinition(),这样就会执行ImportBeanDefinitionRegistrar或者ImportSelector接口的方法
// 或者@Bean注释的方法
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
// 这里判断registry.getBeanDefinitionCount() > candidateNames.length的目的
// 是为了知道reader.loadBeanDefinitions(configClasses)这一步有没有向BeanDefinitionMap中添加新的BeanDefinition
// 实际上就是看配置类(例如AppConfig类会向BeanDefinitionMap中添加bean)
// 如果有,registry.getBeanDefinitionCount()就会大于candidateNames.length
// 这样就需要再次遍历新加入的BeanDefinition,并判断这些bean是否已经被解析过了,如果未解析,需要重新进行解析
// 这里的AppConfig类向容器中添加的bean,实际上在parser.parse()这一步已经全部被解析了
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
// 如果有未解析的类,则将其添加到candidates中,这样candidates不为空,就会进入到下一次的while的循环中
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
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();
}
}- parse方法最终还是调用的doProcessConfigurationClass
- doProcessConfigurationClass处理了内部类
- 处理了 @PropertySource
- 处理了 @ComponentScan
- 处理了 @Import
- 会检查循环引用(stack)
- 支持BeanClassLoaderAware BeanFactoryAware EnvironmentAware ResourceLoaderAware
- ImportSelector
- DeferredImportSelector
- ImportBeanDefinitionRegistrar
- 普通import
- 处理了 @ImportResource
- @Bean
- 处理了interface defaultMethod(如果这个接口中的方法也加了@Bean注解,也需要被解析)
- 解析父类
protected final SourceClass doProcessConfigurationClass( ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException { if (configClass.getMetadata().isAnnotated(Component.class.getName())) { // Recursively process any member (nested) classes first // 处理内部类 processMemberClasses(configClass, sourceClass, filter); } // Process any @PropertySource annotations for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) { if (this.environment instanceof ConfigurableEnvironment) { processPropertySource(propertySource); } else { logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment"); } } // Process any @ComponentScan annotations //直接注入到bd Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { for (AnnotationAttributes componentScan : componentScans) { // The config class is annotated with @ComponentScan -> perform the scan immediately Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // Check the set of scanned definitions for any further config classes and parse recursively if needed for (BeanDefinitionHolder holder : scannedBeanDefinitions) { BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); if (bdCand == null) { bdCand = holder.getBeanDefinition(); } //对扫描出来的类也进行检查(递归) if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } } // Process any @Import annotations //对Import ,ImportSelector ,DeferredImportSelector,ImportBeanDefinitionRegistrar处理 //所谓的处理,都是加到集合中 processImports(configClass, sourceClass, getImports(sourceClass), filter, true); // Process any @ImportResource annotations AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); if (importResource != null) { String[] resources = importResource.getStringArray("locations"); Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader"); for (String resource : resources) { String resolvedResource = this.environment.resolveRequiredPlaceholders(resource); configClass.addImportedResource(resolvedResource, readerClass); } } // Process individual @Bean methods //只是加入到集合中 Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } // Process default methods on interfaces //通过processInterfaces()处理接口的默认方法,从JDK8开始,接口中的方法可以有自己的默认实现, // 因此,如果这个接口中的方法也加了@Bean注解,也需要被解析。 processInterfaces(configClass, sourceClass); // Process superclass, if any //解析父类,如果被解析的配置类继承了某个类,那么配置类的父类也会被进行解析doProcessConfigurationClass() // (父类是JDK内置的类例外,即全类名以java开头的)。 if (sourceClass.getMetadata().hasSuperClass()) { String superclass = sourceClass.getMetadata().getSuperClassName(); if (superclass != null && !superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) { this.knownSuperclasses.put(superclass, configClass); // Superclass found, return its annotation metadata and recurse return sourceClass.getSuperClass(); } } // No superclass -> processing is complete return null; }
postProcessBeanFactory
- 代理Configuration
- 只对加了@Configuration注解进行代理
- 对@Bean的factoryBean处理(把getObject换成getBean)
- 对@Bean的方法调用另外一个@Bean方法处理
- 添加后置处理器ImportAwareBeanPostProcessor
- 为被CGLIB增强时实现了EnhancedConfiguration接口的代理类,设置beanFactory属性
- ImportAware支持
- 首先对Configuration进行cglib代理
- 如果是不同的bean,就看是不是一个方法调用另一个方法,然后决定是直接执行方法,还是从beanfactory中拿
- 如果是factoryBean就再进行一次代理(cglib或Proxy),对getObject进行代理。
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) { Enhancer enhancer = new Enhancer(); //设置父类 enhancer.setSuperclass(configSuperClass); //设置接口实际上就是一个BeanFactoryAware(能够注入BeanFactory) enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class}); enhancer.setUseFactory(false); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); //添加字段$$beanFactory enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader)); // 添加了两个MethodInterceptor。(BeanMethodInterceptor和BeanFactoryAwareMethodInterceptor) // 通过这两个类的名称,可以猜出,前者是对加了@Bean注解的方法进行增强,后者是为代理对象的beanFactory属性进行增强 // 被代理的对象,如何对方法进行增强呢?就是通过MethodInterceptor拦截器实现的 // 类似于SpringMVC中的拦截器,每次执行请求时,都会对经过拦截器。 // 同样,加了MethodInterceptor,那么在每次代理对象的方法时,都会先经过MethodInterceptor中的方法 enhancer.setCallbackFilter(CALLBACK_FILTER); enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes()); return enhancer; }

private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
/**
* Enhance a {@link Bean @Bean} method to check the supplied BeanFactory for the
* existence of this bean object.
* @throws Throwable as a catch-all for any exception that may be thrown when invoking the
* super implementation of the proxied method i.e., the actual {@code @Bean} method
*/
@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
//决定存入时的beanName ,默认是方法名,也可以在@Bean注解上设置
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
// Determine whether this bean is a scoped-proxy
//有没有Scope注解
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.
if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
factoryContainsBean(beanFactory, beanName)) {
Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
if (factoryBean instanceof ScopedProxyFactoryBean) {
// Scoped proxy factory beans are a special case and should not be further proxied
}
else {
// It is a candidate FactoryBean - go ahead with enhancement
// 有两种方法,一种是Proxy,一种是cglib
// 大概就是 beanFactory.getBean(beanName)
return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
}
}
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
// 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);
}
//别人调用自己的方法,就使用引用,从factoryBean拿
return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}
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) {
beanFactory.setCurrentlyInCreation(beanName, false);
}
boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
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) {
useArgs = false;
break;
}
}
}
Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
beanFactory.getBean(beanName));
if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
// Detect package-protected NullBean instance through equals(null) check
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 = 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);
}
}
Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
if (currentlyInvoked != null) {
String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
beanFactory.registerDependentBean(beanName, outerBeanName);
}
return beanInstance;
}
finally {
if (alreadyInCreation) {
beanFactory.setCurrentlyInCreation(beanName, true);
}
}
}
@Override
public boolean isMatch(Method candidateMethod) {
//拦截加了@Bean,并且有beanfactory属性
return (candidateMethod.getDeclaringClass() != Object.class &&
!BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&
BeanAnnotationHelper.isBeanAnnotated(candidateMethod));
}
private ConfigurableBeanFactory getBeanFactory(Object enhancedConfigInstance) {
Field field = ReflectionUtils.findField(enhancedConfigInstance.getClass(), BEAN_FACTORY_FIELD);
Assert.state(field != null, "Unable to find generated bean factory field");
Object beanFactory = ReflectionUtils.getField(field, enhancedConfigInstance);
Assert.state(beanFactory != null, "BeanFactory has not been injected into @Configuration class");
Assert.state(beanFactory instanceof ConfigurableBeanFactory,
"Injected BeanFactory is not a ConfigurableBeanFactory");
return (ConfigurableBeanFactory) beanFactory;
}
/**
* Check the BeanFactory to see whether the bean named <var>beanName</var> already
* exists. Accounts for the fact that the requested bean may be "in creation", i.e.:
* we're in the middle of servicing the initial request for this bean. From an enhanced
* factory method's perspective, this means that the bean does not actually yet exist,
* and that it is now our job to create it for the first time by executing the logic
* in the corresponding factory method.
* <p>Said another way, this check repurposes
* {@link ConfigurableBeanFactory#isCurrentlyInCreation(String)} to determine whether
* the container is calling this method or the user is calling this method.
* @param beanName name of bean to check for
* @return whether <var>beanName</var> already exists in the factory
*/
private boolean factoryContainsBean(ConfigurableBeanFactory beanFactory, String beanName) {
return (beanFactory.containsBean(beanName) && !beanFactory.isCurrentlyInCreation(beanName));
}
/**
* Check whether the given method corresponds to the container's currently invoked
* factory method. Compares method name and parameter types only in order to work
* around a potential problem with covariant return types (currently only known
* to happen on Groovy classes).
*/
private boolean isCurrentlyInvokedFactoryMethod(Method method) {
//ThreadLocal
Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
return (currentlyInvoked != null && method.getName().equals(currentlyInvoked.getName()) &&
Arrays.equals(method.getParameterTypes(), currentlyInvoked.getParameterTypes()));
}
/**
* Create a subclass proxy that intercepts calls to getObject(), delegating to the current BeanFactory
* instead of creating a new instance. These proxies are created only when calling a FactoryBean from
* within a Bean method, allowing for proper scoping semantics even when working against the FactoryBean
* instance directly. If a FactoryBean instance is fetched through the container via &-dereferencing,
* it will not be proxied. This too is aligned with the way XML configuration works.
*
* exposedType--》returnType
*/
private Object enhanceFactoryBean(final Object factoryBean, Class<?> exposedType,
final ConfigurableBeanFactory beanFactory, final String beanName) {
try {
Class<?> clazz = factoryBean.getClass();
boolean finalClass = Modifier.isFinal(clazz.getModifiers());
boolean finalMethod = Modifier.isFinal(clazz.getMethod("getObject").getModifiers());
if (finalClass || finalMethod) {
if (exposedType.isInterface()) {
if (logger.isTraceEnabled()) {
logger.trace("Creating interface proxy for FactoryBean '" + beanName + "' of type [" +
clazz.getName() + "] for use within another @Bean method because its " +
(finalClass ? "implementation class" : "getObject() method") +
" is final: Otherwise a getObject() call would not be routed to the factory.");
}
//使用动态代理
return createInterfaceProxyForFactoryBean(factoryBean, exposedType, beanFactory, beanName);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Unable to proxy FactoryBean '" + beanName + "' of type [" +
clazz.getName() + "] for use within another @Bean method because its " +
(finalClass ? "implementation class" : "getObject() method") +
" is final: A getObject() call will NOT be routed to the factory. " +
"Consider declaring the return type as a FactoryBean interface.");
}
return factoryBean;
}
}
}
catch (NoSuchMethodException ex) {
// No getObject() method -> shouldn't happen, but as long as nobody is trying to call it...
}
//cglib
return createCglibProxyForFactoryBean(factoryBean, beanFactory, beanName);
}
private Object createInterfaceProxyForFactoryBean(final Object factoryBean, Class<?> interfaceType,
final ConfigurableBeanFactory beanFactory, final String beanName) {
return Proxy.newProxyInstance(
factoryBean.getClass().getClassLoader(), new Class<?>[] {interfaceType},
(proxy, method, args) -> {
if (method.getName().equals("getObject") && args == null) {
//从beanFactory中拿
return beanFactory.getBean(beanName);
}
return ReflectionUtils.invokeMethod(method, factoryBean, args);
});
}
private Object createCglibProxyForFactoryBean(final Object factoryBean,
final ConfigurableBeanFactory beanFactory, final String beanName) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(factoryBean.getClass());
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setCallbackType(MethodInterceptor.class);
// Ideally create enhanced FactoryBean proxy without constructor side effects,
// analogous to AOP proxy creation in ObjenesisCglibAopProxy...
Class<?> fbClass = enhancer.createClass();
Object fbProxy = null;
if (objenesis.isWorthTrying()) {
try {
fbProxy = objenesis.newInstance(fbClass, enhancer.getUseCache());
}
catch (ObjenesisException ex) {
logger.debug("Unable to instantiate enhanced FactoryBean using Objenesis, " +
"falling back to regular construction", ex);
}
}
if (fbProxy == null) {
try {
fbProxy = ReflectionUtils.accessibleConstructor(fbClass).newInstance();
}
catch (Throwable ex) {
throw new IllegalStateException("Unable to instantiate enhanced FactoryBean using Objenesis, " +
"and regular FactoryBean instantiation via default constructor fails as well", ex);
}
}
((Factory) fbProxy).setCallback(0, (MethodInterceptor) (obj, method, args, proxy) -> {
if (method.getName().equals("getObject") && args.length == 0) {
//最终还是getBean
return beanFactory.getBean(beanName);
}
return proxy.invoke(factoryBean, args);
});
return fbProxy;
}
}importSelector
- 实现ImportSelector 返回string数组
*高级用法例(不依赖于ComponentScan)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(HelloImportSelector.class)
public @interface HelloServiceScan {
@AliasFor("value")
String[] basePackages() default {};
@AliasFor("basePackages")
String[] value() default {};
}
public class HelloImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(HelloServiceScan.class.getName());
String[] basePackages = (String[]) annotationAttributes.get("basePackages");
if (basePackages == null || basePackages.length == 0) {//HelloServiceScan的basePackages默认为空数组
String basePackage = null;
try {
basePackage = Class.forName(importingClassMetadata.getClassName()).getPackage().getName();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
basePackages = new String[] {basePackage};
}
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
TypeFilter helloServiceFilter = new AssignableTypeFilter(HelloService.class);
scanner.addIncludeFilter(helloServiceFilter);
Set<String> classes = new HashSet<>();
for (String basePackage : basePackages) {
scanner.findCandidateComponents(basePackage).forEach(beanDefinition -> classes.add(beanDefinition.getBeanClassName()));
}
return classes.toArray(new String[classes.size()]);
}
}
@Configuration
@HelloServiceScan("com.elim.spring.core.importselector")
public class HelloConfiguration {
}
@PropertySource
@Configuration
@PropertySource(value = "classpath:application.properties",ignoreResourceNotFound = false)
public class SpringPropertysourceApplication {
@Resource
Environment environment;
@Bean
public TestBean testBean(){
TestBean testBean = new TestBean();
// 读取application.properties中的name
testBean.setName(environment.getProperty("com.spring.name"));
// 读取application.properties中的age
testBean.setAge(Integer.valueOf(environment.getProperty("com.spring.age")));
System.out.println("testBean = " + testBean);
return testBean;
}
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringPropertysourceApplication.class);
TestBean testBean = (TestBean)applicationContext.getBean("testBean");
}
}@Component
@PropertySource("classpath:db.properties")
public class DBConnection {
@Value("${DB_DRIVER_CLASS}")
private String driverClass;
@Value("${DB_URL}")
private String dbUrl;
@Value("${DB_USERNAME}")
private String userName;
@Value("${DB_PASSWORD}")
private String password;
public DBConnection(){}
public void printDBConfigs(){
System.out.println("Db Driver Class = " + driverClass);
System.out.println("Db url = " + dbUrl);
System.out.println("Db username = " + userName);
System.out.println("Db password = " + password);
}
}DeferredImportSelector
- 最后执行的selector,如果有多个支持排序(PriorityOrdered,Orderd)
ImportBeanDefinitionRegistrar
- 高级用法@MapperScan
10ConfigurationClassPostProcessor
https://jiajun.xyz/2020/10/10/java/spring/10ConfigurationClassPostProcessor/