FactoryBean接口示例代码
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
所谓的Smart就是多了2个方法。
isPrototype默认返回值是false也就是默认是单例!
isEagerInit默认返回值是false也就是默认是懒加载!
public interface SmartFactoryBean<T> extends FactoryBean<T> {
default boolean isPrototype() {
return false;
}
default boolean isEagerInit() {
return false;
}
}
示例代码
package factoryBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;
import org.springframework.stereotype.Component;
//为了方便测试可以先注释掉
@Component
@Description("业务类")
public class UserFactoryBean implements SmartFactoryBean {
public UserFactoryBean() {
System.out.println("UserFactoryBean");
}
private int age = 31;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public Object getObject() throws Exception {
System.out.println("getObject");
return new User();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
@Override
public boolean isEagerInit() {
return true;
}
}
package factoryBean;
public class User {
}
package factoryBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("factoryBean")
public class Config {
public Config() {
System.out.println("------------------------Config实例化了");
}
}
package factoryBean;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class ParseTest {
public static void main(String[] args) throws Exception {
start1();
}
public static void start1() throws Exception {
//其中Config.class可以指定为
//包扫描启动:@ComponentScan("tyrant")
//使用xml文件启动:@ImportResource("applicationContext.xml")
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext();
//注册配置类
context.register(Config.class);
context.refresh();
//生成&userFactoryBean的时候会去掉&
//放在一级缓存的是1个 UserFactoryBean
//根据 &userFactoryBean 获取的时候 会先判断是否以&开头如果是
//那么直接返回的是UserFactoryBean
UserFactoryBean userFactoryBean =
(UserFactoryBean)context.getBean("&userFactoryBean");
//生成
User user1 = (User)context.getBean("userFactoryBean");
User user2 = (User)context.getBean("userFactoryBean");
System.out.println(user1==user2);
}
}
生成FactoryBean
@Override
public void preInstantiateSingletons() throws BeansException {
/***
* 放置所有bean的name
*/
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
/***
* 循环所有需要创建的beanName 依次创建bean
*/
for (String beanName : beanNames) {
//获取合并的bd
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
/***
* 非抽象 && 单例 && 非懒加载
*/
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//判断是否实现了FactoryBean接口
//如果实现了FactoryBean接口 那么需要先创建FactoryBean接口的实现类
//bean的名称是真正的beanName
if (isFactoryBean(beanName)) {
//这里虽然用&+beanName做了拼接
//但是在getBean方法中会先去掉&然后去创建FactoryBean接口的实现类
//然后放入1级缓存
//key为 userFactoryBean
//value 为 UserFactoryBean对象
//注意这里是第一次调用getBean 在这里创建的是UserFactoryBean对象
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
//判断是否是Factory
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null
&& factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}else {
//如果是SmartFactoryBean类型
//且SmartFactoryBean的isEagerInit()返回的是true
isEagerInit = (factory instanceof SmartFactoryBean
&&((SmartFactoryBean<?>) factory).isEagerInit());
}
//是否立即加载 如果是立即加载 那么开始创建bean
//在bean非懒加载情况下
//会立刻使用getBean方法创建FactoryBean生成的Bean
//getBean首先从1级缓存查找
//获取到的对象是UserFactoryBean对象
//进入方法getObjectForBeanInstance
if (isEagerInit) {
//FactoryBean走这里 创建bean入口
//在这里创建的是FactoryBean的getObject方法返回的对象
//调用getObejct方法返回的对象
//会被放在工厂的1个Map属性:factoryBeanObjectCache里
getBean(beanName);
}
}
}else {
//非FactoryBean走这里
getBean(beanName);
}
}
}
}
@SuppressWarnings("unchecked")
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType,
@Nullable Object[] args, boolean typeCheckOnly)throws BeansException {
//解析bean 如果以&开头 去掉& 如果是别名获取真正的名字
String beanName = transformedBeanName(name);
Object bean;
//第一次调用getBean会走else 创建的是UserFactoryBean对象
//第二次调用getBean会从缓存中获取到UserFactoryBean对象
//从缓存中获取
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
/***
* 如果实现了FactoryBean接口 需要获取具体对象 要使用下面的方法进行获取
* 如果没有实现FactoryBean接口 会直接返回传递进来的beanInstance
* 这里需要注意传入的beanName是不带& name是带&的
*/
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
/***
如果实现了FactoryBean接口 需要获取具体对象 要使用下面的方法进行获取
如果没有实现FactoryBean接口 会直接返回传递进来的beanInstance
*/
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
return (T) bean;
}
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//如果name是以&开头即获取的是FactoryBean接口的实现类
if (BeanFactoryUtils.isFactoryDereference(name)) {
//如果是NullBean 直接返回
if (beanInstance instanceof NullBean) {
return beanInstance;
}
//进了这个方法beanInstance必须是实现了FactoryBean接口
//否则抛出异常
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
}
//如果不是FactoryBean类型 或者 以&开头 才会进入判断。
//beanInstance是UserFactoryBean
//情况1:name = &userFactoryBean
//beanInstance不是FactoryBean -->false
//&userFactoryBean是以&开头 -->true
//直接返回beanInstance 也就是1级缓存中的对象!
//情况2:name = userFactoryBean
//beanInstance不是FactoryBean -->false
//userFactoryBean是以&开头 -->false
//继续往下走
//如果没有实现FactoryBean接口或者以&开头 直接返回bean
if (!(beanInstance instanceof FactoryBean) ||
BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
//进入了这里说明一定是FactoryBean 并且要拿Factory生产的对象
Object object = null;
if (mbd == null) {
//从缓存中获取 说明肯定是实例化好以后放入了factoryBeanObjectCache
//return this.factoryBeanObjectCache.get(beanName);
object = getCachedObjectForFactoryBean(beanName);
}
//第一次从缓存拿是空对象
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
//从Factory中获取
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
单例多例控制
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//单例放缓存
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
return object;
}
beforeSingletonCreation(beanName);
try {
//生成代理对象
object = postProcessObjectFromFactoryBean
(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException
(beanName,"PostProcessFactoryBean's object failed");
}
finally {
afterSingletonCreation(beanName);
}
}
//Factory是单例多例都是由这个方法控制
//单例放缓存
//多例则每次都创建新对象
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
//多例则每次都创建新对象
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException
(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
@Bean修饰的方法示例代码
package parse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
public class Config {
public Config() {
System.out.println("------------------------Config实例化了");
}
@Bean
public User getUser(){
return new User();
}
}
package parse;
import org.springframework.context.annotation.DeferredImportSelector;
import org.springframework.context.annotation.Description;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.stereotype.Component;
//为了方便测试可以先注释掉
//@Component
@Description("业务类")
public class User implements DeferredImportSelector {
private int age =31;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
String name = ImportedByUser.class.getName();
return new String[]{name};
}
}
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
public class ParseTest {
public static void main(String[] args) throws InterruptedException {
start1();
}
public static void start1() {
//其中Config.class可以指定为
//包扫描启动:@ComponentScan("tyrant")
//使用xml文件启动:@ImportResource("applicationContext.xml")
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
//注册配置类
context.register(Config.class);
context.refresh();
User config = (User) context.getBean("user");
Object user = context.getBean("getUser");
//返回true
System.out.println(config.getUser() == user);
//为什么要用代理呢?
//原因是获取user的方式有2种
//1.config.getUser()
//2.context.getBean("getUser");
//如果是单例模式 2种方式返回的对象不一样 那不就有问题吗?!
}
}
@Bean代理
老规矩,首先祭出我们的配置类
@ComponentScan("com.app")
@Configuration
public class Config {
}
启动spring
public class SpringTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
context.register(Config.class);
context.refresh();
System.out.println(context.getBean(Config.class));
}
}
spring启动后,我们获取Config配置对象,打印结果如下:
com.config.Configefc56a4d@33e5ccce不言而喻,Conifg被CGLIB动态代理成了另一个增强型的对象。
我们看,Config类上有个@Configuration注解,这个注解的作用前面文章讲过好多了,表示这是一个配置类,spring扫描注册的时候会解析这个类,但是如果把这个注解去掉,我们看一下打印结果:
此时,spring就没有对它进行动态代理了。其实,Configuration的作用远不止如此,我们继续测试。 首先生成两个业务类E和F
public class E {
}
public class F {
}
通过@Bean方式注入
@ComponentScan("com.app")
@Configuration
public class Config {
@Bean
public E getE(){
System.out.println("get class E");
return new E();
}
@Bean
public F getF(){
getE();
System.out.println("get class F");
return new F();
}
}
getE方法会生成E类的实例对象,getF方法在生成F实例对象的同时,会再一次调用getE方法生成一个E实例对象,会吗?
public class SpringTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Config.class);
context.refresh();
System.out.println(context.getBean(E.class));
System.out.println(context.getBean(F.class));
}
}
打印结果:
getE在整个过程中,只被调用了一次,换句话讲,getE()方法在getF()中并没有起作用!好神奇!如果去掉@Configuration这个注解,情况就不一样了,读者可自行测试。
spring是怎么判断Config是否需要代理的呢?
context.refresh()完成了启动过程,跟进代码找到invokeBeanFactoryPostProcessors(beanFactory);,继续跟进,第一行PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());,invokeBeanFactoryPostProcessors这个方法就是调用各种后置处理器的,前面博文也讲过太多了,这里不再详述,如果读者看到这里有点懵的话,建议按顺序阅读本专题。继续,ConfigurationClassPostProcessor完成了扫描注册,完事找到方法里这么一行代码
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
这行代码跟进去,看下源码
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
假设我们程序员没有提供后置处理器的话,这里的postProcessors只有一个,就是ConfigurationClassPostProcessor,怎么老是这个后置处理器,这个类实现了BeanDefinitionRegistryPostProcessor接口,而BeanDefinitionRegistryPostProcessor接口又继承了BeanFactoryPostProcessor接口,ConfigurationClassPostProcessor通过BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法完成了扫描注册,spring紧接着调用ConfigurationClassPostProcessor所实现BeanFactoryPostProcessor接口的postProcessBeanFactory方法完成后续处理,这个后续处理就是上面的源码啦!
源码很简单,就是调用了后置处理器的postProcessBeanFactory方法,在这里就是ConfigurationClassPostProcessor的postProcessBeanFactory方法,我们看下它的源码
/**
* Prepare the Configuration classes for servicing bean requests at runtime
* by replacing them with CGLIB-enhanced subclasses.
* 准备配置类以便在运行时为bean请求提供服务,方法是用cglib增强的子类替换它们
* 也就是使用cglib的代理的方式增强beanDefinition。
*/
@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 ");
}
this.factoriesPostProcessed.add(factoryId);
//如果有BD未解析 继续解析
if (!this.registriesPostProcessed.contains(factoryId)) {
//可以看到这里还在解析BD
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
enhanceConfigurationClasses(beanFactory);
beanFactory
.addBeanPostProcessor
(new ImportAwareBeanPostProcessor(beanFactory));
}
前面是对当前beanDefinitionRegister做判断,是否已经处理过和注册过,不出意外的话就会进入enhanceConfigurationClasses(beanFactory);
这个方法顾名思义,就是增强配置类。
这也解释了为什么前面的Config加上@Configuration就会被动态代理。
那么下面的重点就是阅读enhanceConfigurationClasses的源码喽。
源码首先找出所有的带有@Configuration注解的配置类然后做判断
1.必须是抽象BeanDefinition
2.不能在单例池已经被创建
并存放到LinkedHashMap集合中。在这里只有咱们的Config配置类符合,然后遍历集合进行增强处理。
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs =
new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
//如果配置类是FULL
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
//如果不是抽象BD 抛出异常
if (!(beanDef instanceof AbstractBeanDefinition)) {
//Cannot enhance @Configuration bean definition
//since it is not stored in an
// AbstractBeanDefinitionsubclass
throw new BeanDefinitionStoreException();
}
else if (beanFactory.containsSingleton(beanName)) {
// Cannot enhance @Configuration bean definition
// 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
}
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
if (configBeanDefs.isEmpty()) {
// nothing to enhance -> return immediately
return;
}
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry :
configBeanDefs.entrySet()) {
//前面已经做过InstanceOf判断 这里直接取出来
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) {
//重点方法
Class<?> enhancedClass =
enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
//使用创建的增强classs替换原来的配置类的class
beanDef.setBeanClass(enhancedClass);
}
}
}
catch (Throwable ex) {
throw new IllegalStateException
("Cannot load configuration class");
}
}
}
首先,根据BeanDefinition获取对应的class对象
Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
然后就是增强处理:
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
下一个分析enhance方法看如何增强的
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
return configClass;
}
Class<?> enhancedClass = createClass
(newEnhancer(configClass, classLoader));
return enhancedClass;
}
看这个方法的注释,加载指定的类并生成一个CGLIB代理的子类。
源码最重要的一行 Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
首先分析newEnhancer方法:
/**
* Creates a new CGLIB {@link Enhancer} instance.
*/
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
Enhancer enhancer = new Enhancer();
//把业务类,这里是Config,设置成代理类的父类
enhancer.setSuperclass(configSuperClass);
//代理类实现EnhancedConfiguration接口
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
enhancer.setUseFactory(false);
//设置代理类名称的生成策略
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;
}
看注释,生成一个CGLIB代理实例,里面用到了Enhancer ,不就是文章开头讲的那个小demo吧! 然后就是createClass方法:
private Class<?> createClass(Enhancer enhancer) {
//创建配置类的子类 也就是代理类
Class<?> subclass = enhancer.createClass();
//注册方法拦截器
Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
return subclass;
}
通过Enhancer生成一个被代理类config的子类,也就是代理类。
代理结束后返回,一直返回到enhanceConfigurationClasses方法的Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);,
这时候的enhancedClass 就是代理类了,OK,这行代码执行完后往下执行了beanDef.setBeanClass(enhancedClass);,
意思很明朗,就是将Config的BeanDefinitino中的class替换成代理class。
之后就会实例化代理类而不是Config类本身。
现在解释清楚了,为什么Config加上@Configuration注解后就会被spring动态代理。再解释上文getE()方法在getF()中并没有起作用!
很明显,spring既然代理了Config,那么执行getF方法时不是真的执行Config里的getF方法,而是执行代理类的getF方法,在哪里执行的呢?
newEnhancer方法中,有一个过滤器的设置
enhancer.setCallbackFilter(CALLBACK_FILTER);
CALLBACK_FILTER是一个变量:
private static final Callback[] CALLBACKS = new Callback[] {
new BeanMethodInterceptor(),
new BeanFactoryAwareMethodInterceptor(),
NoOp.INSTANCE
};
private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);
文章一开始举的CGLIB案例中,就是通过回调完成了方法的拦截对吧?
这里有两个回调类BeanMethodInterceptor和BeanFactoryAwareMethodInterceptor。
他俩组成了一个回调链,依次调用而已。
这两个回调其实是在bean的生命周期过程中调用的,这是后续章节的内容,这里我们简单讲下,后面会详细讲。
在实例化过程中,我们主要关注BeanMethodInterceptor这个回调。
我们在调用getF方法时,会先执行回调BeanMethodInterceptor中的intercept方法。intercept方法很复杂很复杂,大概意思是,在执行getF中的getE方法时判断getE返回的bean是否已经实例化了,如果已经实例化了就不再调用该方法了。
getF和getE调用的时候都是先调用回调函数的,都会判断是否已经实例化了。
spring以此保证@Bean返回的实例是单例的。
本篇讲的比较简单比较浅,估计读者也是明白个大概的原理,因为这里涉及到后续的知识,没关系,后面会再详细讲解的。
这里大家主要了解
- CGLIB的使用
- Spring是如何利用到CGLIB的
- 如何使用内置的代理回调类BeanMethodInterceptor、BeanFactoryAwareMethodInterceptor来增强我们的目标类方法的即可。
- BeanDefinition将对应的class用代理类替换掉业务类,后期实例化的是代理类
解析BeanDefinition
递归解析配置类的内部类
private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
//找到内部类,因为内部类也可能是一个配置类
Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
if (!memberClasses.isEmpty()) {
List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
for (SourceClass memberClass : memberClasses) {
//判断内部类是不是配置类,上文讲过了如何判断是不是配置类
if (ConfigurationClassUtils.isConfigurationCandidate
(memberClass.getMetadata()) &&
!memberClass.getMetadata().getClassName().equals
(configClass.getMetadata().getClassName())) {
//放入候选集合
candidates.add(memberClass);
}
}
//对配置类进行那个排序,上文也讲过了
OrderComparator.sort(candidates);
//1)出现配置类循环导入,直接报错
for (SourceClass candidate : candidates) {
if (this.importStack.contains(configClass)) {
this.problemReporter.error
(new CircularImportProblem(configClass, this.importStack));
}
else {
//将配置类入栈
this.importStack.push(configClass);
try {
// 递归调用processConfigurationClass方法,也许内部类还有内部类
//其实,工作中我们不会内部类嵌套内部类再嵌套内部类再嵌套。。。
processConfigurationClass
(candidate.asConfigClass(configClass));
}
finally {
//解析完出栈
this.importStack.pop();
}
}
}
}
}
递归处理@CompentScan
// Process any @ComponentScan annotations
// 获取配置类上的@ComponentScan注解属性
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
//构造一个Classpath扫描器
//注册了1个类型过滤器@Component,@Component包含 @Controller @Repository @Service
// 获取并解析BasePackage属性 获取需要扫描的包
// 然后根据classpath扫描器中的过滤器进行过滤
// 如果include过滤器返回的是true && exclude过滤器返回的是false
//那么就加入candidates并返回
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse
(componentScan, sourceClass.getMetadata().getClassName());
//扫描的是所有的class 返回的并不是所有的
//首先beanConfig配置类会被排除,因为注册了一个beanConfig的排除过滤器
//没有加@Conponent的也会被排除 排除了 TestOrangeCondition 和 Mybean
//因此剩下了4个
/**
0 = Aop.class
1 = AopLog.class
4 = MyPlatformTransactionManager.class
6 = TestRegisterResolvableDependency.class
*/
//遍历扫描到的BeanDefinitions 判断是否需要解析
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand =
holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
//判断是否属于候选类
//判断是否存在@Configuration注解
//判断是否存在@Bean修饰的方法
//判断是否被下面这些注解修饰过
//如果是继续被当成配置类解析
/*
candidateIndicators.add(Component.class.getName());
candidateIndicators.add(ComponentScan.class.getName());
candidateIndicators.add(Import.class.getName());
candidateIndicators.add(ImportResource.class.getName());
*/
if (ConfigurationClassUtils.checkConfigurationClassCandidate
(bdCand, this.metadataReaderFactory)) {
//解析 解析出来的BeanDefinition
//这里是一个递归处理 又进入了processConfigurationClass方法
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
递归处理@Import
立刻处理ImportSelector
延迟处理DeferredImportSelector
延迟处理ImportBeanDefinitionRegistrar
ImportSelector、DeferredImportSelector、ImportBeanDefinitionRegistrar
public interface ImportSelector {
String[] selectImports(AnnotationMetadata importingClassMetadata);
}
public interface DeferredImportSelector extends ImportSelector {
@Nullable
default Class<? extends Group> getImportGroup() {
return null;
}
interface Group {
void process(AnnotationMetadata metadata, DeferredImportSelector selector);
Iterable<Entry> selectImports();
class Entry {
private final AnnotationMetadata metadata;
private final String importClassName;
public Entry(AnnotationMetadata metadata, String importClassName) {
this.metadata = metadata;
this.importClassName = importClassName;
}
public AnnotationMetadata getMetadata() {
return this.metadata;
}
public String getImportClassName() {
return this.importClassName;
}
@Override
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
}
if (other == null || getClass() != other.getClass()) {
return false;
}
Entry entry = (Entry) other;
return (this.metadata.equals(entry.metadata)
&& this.importClassName.equals(entry.importClassName));
}
@Override
public int hashCode() {
return (this.metadata.hashCode() * 31 +
this.importClassName.hashCode());
}
@Override
public String toString() {
return this.importClassName;
}
}
}
}
@ImportResource导入资源加入集合
将@Bean方法加入集合
递归处理接口@Bean默认方法
延迟处理DeferredImportSelector
deferredImportSelectorHandler.process()
入口:this.deferredImportSelectorHandler.process();
public void process() {
//在处理@Import注解时
//DeferredImportSelector的实现类已经实例化
//并封装为DeferredImportSelectorHolder
//放入deferredImportSelectors集合
List<DeferredImportSelectorHolder> deferredImports
= this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
DeferredImportSelectorGroupingHandler handler
= new DeferredImportSelectorGroupingHandler();
deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
deferredImports.forEach(handler::register);
//进入这里
//handler是DeferredImportSelectorHolder
handler.processGroupImports();
}
}
finally {
this.deferredImportSelectors = new ArrayList<>();
}
}
}
processGroupImports
public void processGroupImports() {
for (DeferredImportSelectorGrouping grouping :
this.groupings.values()) {
//调用getImports
grouping.getImports().forEach(entry -> {
ConfigurationClass configurationClass =
this.configurationClasses.get(entry.getMetadata());
try {
//调用processImports方法
//也就是5.4步的processImports方法
//将这些被DeferredSelectImporter接口导入的类
//作为普通的@Configuration的Class被解析
processImports
(configurationClass,
asSourceClass(configurationClass),
asSourceClasses(entry.getImportClassName()),
false);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates
"for configuration class ", ex);
}
});
}
}
getImports
public Iterable<Group.Entry> getImports() {
for (DeferredImportSelectorHolder deferredImport :
this.deferredImports) {
//调用process方法
this.group.process
(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
//返回的是调用Selector的selectImports
return this.group.selectImports();
}
//DefaultDeferredImportSelectorGroup#process
@Override
public void process(AnnotationMetadata metadata,
DeferredImportSelector selector) {
//调用Selector接口的selectImports方法
//返回的importClassName是:deferred.AopLog
for (String importClassName : selector.selectImports(metadata)) {
//往imports里面添加 1个 Entry
//Entry里封装了 deferred.AopLog
this.imports.add(new Entry(metadata, importClassName));
}
}
processImports
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
return;
}
//检测Import循环依赖
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}else {
this.importStack.push(configClass);
try {
//遍历的importCandidates 是@Import导入的类集合
for (SourceClass candidate : importCandidates) {
//如果导入的类是实现了ImportSelector接口
if (candidate.isAssignable(ImportSelector.class)) {
// 处理 ImportSelector
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
//判断是否是DeferredImportSelector 延迟加载的selector
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle
(configClass, (DeferredImportSelector) selector);
}
//ImportSelector 立即加载的selector
else {
//普通的ImportSelector ,执行其selectImports方法,获取需要导入的类的全限定类名数组
String[] importClassNames
= selector.selectImports(currentSourceClass.getMetadata());
//遍历selectImports方法导入的类名
Collection<SourceClass> importSourceClasses
= asSourceClasses(importClassNames);
// 递归调用
processImports
(configClass, currentSourceClass, importSourceClasses, false);
}
}
//处理实现ImportBeanDefinitionRegistrar接口的类
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
BeanUtils.instantiateClass
(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar
(registrar, currentSourceClass.getMetadata());
}else {
//@Import导入的类既没有实现ImportSelector接口也没有实现
//ImportBeanDefinitionRegistrar接口
//也就是最后@Import导入的类一定会被当做配置类解析
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar
// ->process it as an @Configuration class
// 普通 @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(),
candidate.getMetadata().getClassName());
//deferred.AOP被作为配置类导入
// 递归解析导入的@Configuration class
// 递归解析导入的@Configuration class
// 递归解析导入的@Configuration class
// 递归解析导入的@Configuration class
processConfigurationClass(candidate.asConfigClass(configClass));
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
this.importStack.pop();
}
}
}
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
//判断是否需要跳过 比如有@Conditional注解就要跳过
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
// Explicit bean definition found, probably replacing an import.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
// Recursively process the configuration class and its superclass hierarchy.
SourceClass sourceClass = asSourceClass(configClass);
do {
//真正解析的地方
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
this.configurationClasses.put(configClass, configClass);
}
loadBeanDefinitions(configClasses);
处理@Bean方法
处理ImportedResources
处理ImportBeanDefinitionRegistrar
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) &&
this.registry.containsBeanDefinition(beanName)){
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass
(configClass.getMetadata().getClassName());
return;
}
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//处理@Bean对应的方法
//将他们注册到beanDefinitionMap中
//其实是注册了一个bean
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
//导入ImportedResources
//解析文件导入beanDefinition
loadBeanDefinitionsFromImportedResources
(configClass.getImportedResources());
//导入Registrars
loadBeanDefinitionsFromRegistrars
(configClass.getImportBeanDefinitionRegistrars());
}