引言
在Spring IOC:ConfigurationClassPostProcessor解析提到对于配置类,不管是否使用了@Configuration都会进行注解的解析,那么@Configuration到底还有什么其他的作用呢?
Appconfig配置类
@Configuration
@ComponentScan("com.st")
public class Appconfig {
@Bean
public UserDao getUserDao(){
return new UserDao();
}
@Bean
public UserDao2 getUserDao2(){
getUserDao();
return new UserDao2();
}
}
新建UserDao对象
package com.st.dao;
public class UserDao {
public UserDao() {
System.out.println("userDao1--init");
}
public void query(){}
}
新建UserDao2对象
package com.st.dao;
public class UserDao2 {
public UserDao2() {
System.out.println("UserDao2--init");
}
public void query(){}
}
package com.st.test;
import com.st.config.Appconfig;
import com.st.config.MyBeanFactoryPostProcessor;
import com.st.dao.Indexdao;
import com.st.dao.Indexdao2;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Appconfig.class);
//context.refresh();
//context.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
context.refresh();
//Indexdao2 indexdao = context.getBean(Indexdao2.class);
//System.out.println(indexdao.getClass().getName());
// System.out.println(indexdao.hashCode()+"-------"+indexdao1.hashCode());
}
}
当我们在配置类中使用了@Bean注解,在getUserDao2()中调用了getUserDao()
可以看到getUserDao()中创建了一个UserDao对象,而调用new UserDao()必然会执行对应的构造方法,所以在这里UserDao的无参构造会输出几次init呢?
执行结果:
说明了getUserDao()返回的是已经创建好的单例对象
现在把@Configuration去掉
执行结果:
@Configuration进行Cglib增强
在上一章节讲到了ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法,spring执行完这个方法之后还会执行这个类的postProcessBeanFactory方法。就是在这里对@Configuration进行了Cglib增强,使得getUser()时返回的是已产生的单例对象
@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);
// postProcessorBeanFactory()方法也会调用processConfigBeanDefinitions方法,为了避免重复执行,
// 所以在执行方法之前会先生成一个id,将id放入到一个set当中,每次执行之前
// 先判断id是否存在,所以在此处,不会进入到if语句中
if (!this.registriesPostProcessed.contains(factoryId)) {
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
//对@Configuration进行Cglib增强
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
进入enhanceConfigurationClasses(beanFactory)正式对@Configuration进行Cglib增强
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
//拿到全注解的配置类
//return CONFIGURATION_CLASS_FULL.equals(beanDef.getAttribute(CONFIGURATION_CLASS_ATTRIBUTE));
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
//省略。。。
}
}
if (configBeanDefs.isEmpty()) {
// nothing to enhance -> return immediately
return;
}
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
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
try {
// Set enhanced subclass of the user-specified bean class
Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
if (configClass != null) {
//调用ConfigurationClassEnhancer.enhance()方法创建增强类
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Replacing bean definition '%s' existing class '%s' with " +
"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
beanDef.setBeanClass(enhancedClass);
}
}
}
catch (Throwable ex) {
throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}
调用ConfigurationClassEnhancer.enhance()方法创建增强类,重点关注newEnhancer(configClass, classLoader)
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
//省略。。。
}
//重点关注newEnhancer(configClass, classLoader)
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
if (logger.isDebugEnabled()) {
logger.debug(String.format("Successfully enhanced %s; enhanced class name is: %s",
configClass.getName(), enhancedClass.getName()));
}
return enhancedClass;
}
为appconfig创建cglib,这里的重点是为cglib对象加入了父类,因为cglib是基于继承实现的。还有就是加入了两个拦截器BeanMethodInterceptor,BeanFactoryAwareMethodInterceptor,实现了config类的增强
/**
* Creates a new CGLIB {@link Enhancer} instance.
*/
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
Enhancer enhancer = new Enhancer();
//增强父类,Cglib的代理是基于父类的
enhancer.setSuperclass(configSuperClass);
//增强接口,为什么要增强接口?便于判断,表示一个类被增强了
//基于接口的EnhancedConfiguration的父接口BeanFactoryAware中的setBeanFactory方法
//设置这个变量的值为当前Context中的beanFactory,这个cglib代理类就有了beanFactory,这样就可以通过beanFactory获取对象了
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
enhancer.setUseFactory(false);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
/*BeanFactoryAwareGeneratorStrategy是一个生成策略
主要是为了生成的Cglib类中设置属性添加成员变量$$beanFactory
BeanFactoryAwareGeneratorStrategy#transform declare_field(Constants.ACC_PUBLIC, BEAN_FACTORY_FIELD, Type.getType(BeanFactory.class), null);
*/
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
//当前的CALLBACK_FILTER为ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);
//CALLBACKS 为 new Callback[] {
// new BeanMethodInterceptor(),//调用intercept方法实现拦截,对加了@Bean注解的方法进行增强
// new BeanFactoryAwareMethodInterceptor(),//调用intercept方法实现拦截,为代理对象的beanFactory属性进行增强
// NoOp.INSTANCE }
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;
}
BeanMethodInterceptor#intercept方法
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
//通过enhancedConfigInstance中cglib的成员遍历$$beanFactory获得beanFactory
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
// Determine whether this bean is a scoped-proxy
Scope scope = AnnotatedElementUtils.findMergedAnnotation(beanMethod, Scope.class);
if (scope != null && scope.proxyMode() != ScopedProxyMode.NO) {
String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
beanName = scopedBeanName;
}
}
//首先检查当前bean是不是一个FactoryBean,如果是就创建一个代理子类调用getObject方法返回一个bean实例
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
return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
}
}
//判断执行的方法和调用的方法是不是同一个方法
//当执行到@Bean方法内调用其他getUserObject方法这里的执行方法和调用方法就不是同一个了
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.isWarnEnabled() &&
BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
}
//创建bean并返回
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}
//返回已经创建好的bean实例
return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}
BeanFactoryAwareMethodInterceptor#intercept 为代理对象设置beanFactory属性
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");
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;
}