近段时间小编一直在啃源码,包括mybatis,spring,springboot,dubbo等等。有输入就得有输出要不,刚刚啃完就忘记了。确实比较难啃,当然也听过一系列大佬学习源码的过程,也看过相应的视频。现在为了巩固自己所学,也为了验证自己所学,特将此过程记录,首先就是spring核心,ioc和aop,这过了18年还经久不衰,可见当年作者的思想领先多少岁月。好了废话不多说,看建模基石。
这里写了一个main方法使用AnnotationConfigApplicationContext 容器,扫描对应的包com.dtyunxi.yundt.test,注册相关的bean,非常简单
@ComponentScan(basePackages = "com.dtyunxi.yundt.test")
public class BeanDefinitionPreTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(BeanDefinitionPreTest.class);
Object noMean = applicationContext.getBean("noMean");
System.out.println(noMean);
}
com.dtyunxi.yundt.test包下只有一个实体类
@Component
public class NoMean {
public NoMean(){
System.out.println("我被初始化了");
}
}
打印结果
我被初始化了
com.dtyunxi.yundt.test.NoMean@1f1c7bf6
这大概是怎样一个流程呢,小编先用伪代码告诉大家结果
//伪代码
//加载过来的类相当于小编的NoMean的class对象这里可以有xml文件注解等等现在大家用注解比较多基本没有了这样配置了,不过原理都一样
List<Class> classList = new ArrayList<>();
Map<String, BeanDefinition> map = new ConcurrentHashMap<>();
//遍历class集合 生成beanDefintion
for (Class aClass : classList) {
GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
//设置对应的一系列值,最重要的是beanClass
genericBeanDefinition.setBeanClass(aClass);
genericBeanDefinition.setBeanClassName("className");
//genericBeanDefinition.setScope("singleton");
//genericBeanDefinition.setDependsOn("otherClass");
//genericBeanDefinition.setLazyInit(false);
genericBeanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
map.put("className",genericBeanDefinition);
}
//遍历用beanDefintion去实例化类
for (Map.Entry<String, BeanDefinition> stringBeanDefinitionEntry : map.entrySet()) {
GenericBeanDefinition value = (GenericBeanDefinition)stringBeanDefinitionEntry.getValue();
//一系列判断 比方说单例比方说是否懒加载等等
if(value.isSingleton()){
//生成对应初始化对象
Object o = value.getBeanClass().newInstance();
//放入容器中
put(o)
}
}
spring当然远远没有那么简单,他会做的事情更多各种校验处理,然后再放入容器,放入容器之前还可以各种修改但大体流程基本如此,稍后小编带大家一行一行看源码,清清楚楚明明白白。
这边属于正常流程,但是放入Map
首先我们实现BeanFactoryPostProcessor 接口并加上注解,让spring容器能够扫描应用进去,然后实现里面唯一的方法,方法的参数你可以理解为对上面beanDefinition的map的封装
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition noMean = (GenericBeanDefinition)beanFactory.getBeanDefinition("noMean");
//改成多例的
noMean.setScope("prototype");
//偷梁换柱修改类
noMean.setBeanClass(HasMean.class);
}
}
HasMean类,这边我们并没有加入注解让spring管理
public class HasMean {
public HasMean(){
System.out.println("hasMean我被初始化了");
}
}
修改测试类
@ComponentScan(basePackages = "com.dtyunxi.yundt.test")
public class BeanDefinitionPreTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(BeanDefinitionPreTest.class);
Object noMean = applicationContext.getBean("noMean");
Object noMean2 = applicationContext.getBean("noMean");
System.out.println(noMean);
System.out.println(noMean2);
}
}
打印结果
hasMean我被初始化了
hasMean我被初始化了
com.dtyunxi.yundt.test.HasMean@4461c7e3
com.dtyunxi.yundt.test.HasMean@351d0846
上面代码的流程图大概是这样的
然后其实我们关注的是存放definition的map什么时候有值(除了spring初始化的一些beanDefiniton),我们来看一下spring的容器初始化源码,在小编示例的第一个方法中就是用这个类。着重看注释
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
public AnnotationConfigApplicationContext() {
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
this.reader = new AnnotatedBeanDefinitionReader(this);
createAnnotatedBeanDefReader.end();
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
super(beanFactory);
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
//这行代码
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
//初始化他自己之前需要初始化他继承的类,他继承的类请看下个代码块
this();
this.register(componentClasses);
this.refresh();
}
public AnnotationConfigApplicationContext(String... basePackages) {
this();
this.scan(basePackages);
this.refresh();
}
public void setEnvironment(ConfigurableEnvironment environment) {
super.setEnvironment(environment);
this.reader.setEnvironment(environment);
this.scanner.setEnvironment(environment);
}
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
this.reader.setBeanNameGenerator(beanNameGenerator);
this.scanner.setBeanNameGenerator(beanNameGenerator);
this.getBeanFactory().registerSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator", beanNameGenerator);
}
public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
this.reader.setScopeMetadataResolver(scopeMetadataResolver);
this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
}
public void register(Class<?>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register").tag("classes", () -> {
return Arrays.toString(componentClasses);
});
this.reader.register(componentClasses);
registerComponentClass.end();
}
public void scan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
StartupStep scanPackages = this.getApplicationStartup().start("spring.context.base-packages.scan").tag("packages", () -> {
return Arrays.toString(basePackages);
});
this.scanner.scan(basePackages);
scanPackages.end();
}
public <T> void registerBean(@Nullable String beanName, Class<T> beanClass, @Nullable Supplier<T> supplier, BeanDefinitionCustomizer... customizers) {
this.reader.registerBean(beanClass, beanName, supplier, customizers);
}
}
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
@Nullable
private ResourceLoader resourceLoader;
private boolean customClassLoader;
private final AtomicBoolean refreshed;
//这里最主要的是this.beanFactory = new DefaultListableBeanFactory();
//这个工厂很重要啊 里面封装各种参数,小伙伴可以自行看一下,这边不贴出代码了
public GenericApplicationContext() {
this.customClassLoader = false;
this.refreshed = new AtomicBoolean();
this.beanFactory = new DefaultListableBeanFactory();
}
}
打断点,这里beanFactory包含了刚刚所讲的beanDefinitionMap
咱们挑一个spring容器初始化就封装到beanDefinitionMap里面的类,并讲一下它的作用,其他靠各位同学慢慢研究了。
首先不知道大家好不好奇在哪儿加进去这些类的,初始化时从这个工具类AnnotationConfigUtils 加载封装进去的,有兴趣可以看一下。
public abstract class AnnotationConfigUtils {
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
public static final String CONFIGURATION_BEAN_NAME_GENERATOR = "org.springframework.context.annotation.internalConfigurationBeanNameGenerator";
public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
/** @deprecated */
@Deprecated
public static final String REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalRequiredAnnotationProcessor";
public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalCommonAnnotationProcessor";
public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalPersistenceAnnotationProcessor";
private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME = "org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor";
public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME = "org.springframework.context.event.internalEventListenerProcessor";
public static final String EVENT_LISTENER_FACTORY_BEAN_NAME = "org.springframework.context.event.internalEventListenerFactory";
private static final boolean jsr250Present;
private static final boolean jpaPresent;
public AnnotationConfigUtils() {
}
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, (Object)null);
}
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet(8);
RootBeanDefinition def;
if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalConfigurationAnnotationProcessor")) {
def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"));
}
if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalAutowiredAnnotationProcessor")) {
def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"));
}
if (jsr250Present && !registry.containsBeanDefinition("org.springframework.context.annotation.internalCommonAnnotationProcessor")) {
def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalCommonAnnotationProcessor"));
}
if (jpaPresent && !registry.containsBeanDefinition("org.springframework.context.annotation.internalPersistenceAnnotationProcessor")) {
def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName("org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor", AnnotationConfigUtils.class.getClassLoader()));
} catch (ClassNotFoundException var6) {
throw new IllegalStateException("Cannot load optional framework class: org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor", var6);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalPersistenceAnnotationProcessor"));
}
if (!registry.containsBeanDefinition("org.springframework.context.event.internalEventListenerProcessor")) {
def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.event.internalEventListenerProcessor"));
}
if (!registry.containsBeanDefinition("org.springframework.context.event.internalEventListenerFactory")) {
def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.event.internalEventListenerFactory"));
}
return beanDefs;
}
private static BeanDefinitionHolder registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(2);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
@Nullable
private static DefaultListableBeanFactory unwrapDefaultListableBeanFactory(BeanDefinitionRegistry registry) {
if (registry instanceof DefaultListableBeanFactory) {
return (DefaultListableBeanFactory)registry;
} else {
return registry instanceof GenericApplicationContext ? ((GenericApplicationContext)registry).getDefaultListableBeanFactory() : null;
}
}
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
processCommonDefinitionAnnotations(abd, abd.getMetadata());
}
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
} else if (abd.getMetadata() != metadata) {
lazy = attributesFor(abd.getMetadata(), (Class)Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
}
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
if (dependsOn != null) {
abd.setDependsOn(dependsOn.getStringArray("value"));
}
AnnotationAttributes role = attributesFor(metadata, Role.class);
if (role != null) {
abd.setRole(role.getNumber("value").intValue());
}
AnnotationAttributes description = attributesFor(metadata, Description.class);
if (description != null) {
abd.setDescription(description.getString("value"));
}
}
static BeanDefinitionHolder applyScopedProxyMode(ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
return definition;
} else {
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
}
@Nullable
static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, Class<?> annotationClass) {
return attributesFor(metadata, annotationClass.getName());
}
@Nullable
static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, String annotationClassName) {
return AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annotationClassName, false));
}
static Set<AnnotationAttributes> attributesForRepeatable(AnnotationMetadata metadata, Class<?> containerClass, Class<?> annotationClass) {
return attributesForRepeatable(metadata, containerClass.getName(), annotationClass.getName());
}
static Set<AnnotationAttributes> attributesForRepeatable(AnnotationMetadata metadata, String containerClassName, String annotationClassName) {
Set<AnnotationAttributes> result = new LinkedHashSet();
addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName, false));
Map<String, Object> container = metadata.getAnnotationAttributes(containerClassName, false);
if (container != null && container.containsKey("value")) {
Map[] var5 = (Map[])((Map[])container.get("value"));
int var6 = var5.length;
for(int var7 = 0; var7 < var6; ++var7) {
Map<String, Object> containedAttributes = var5[var7];
addAttributesIfNotNull(result, containedAttributes);
}
}
return Collections.unmodifiableSet(result);
}
private static void addAttributesIfNotNull(Set<AnnotationAttributes> result, @Nullable Map<String, Object> attributes) {
if (attributes != null) {
result.add(AnnotationAttributes.fromMap(attributes));
}
}
static {
ClassLoader classLoader = AnnotationConfigUtils.class.getClassLoader();
jsr250Present = ClassUtils.isPresent("javax.annotation.Resource", classLoader);
jpaPresent = ClassUtils.isPresent("javax.persistence.EntityManagerFactory", classLoader) && ClassUtils.isPresent("org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor", classLoader);
}
}
咱们挑一个org.springframework.context.annotation.internalAutowiredAnnotationProcessor来讲一下,这是内置的autowired注解解析器,看到这儿大家是不是恍然大悟,我们的@Autowired这个注解就是靠它来处理的,它不需要我们自己注入,所以spring就提前注入完成了,它封装的beanDefiniton下面有beanClass为org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor,我们看下他源码解释,这边代码比较多,贴一个比较重要的即可
org.springframework.beans.factory.annotation public class AutowiredAnnotationBeanPostProcessor
extends Object
implements SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware
---------------------------------------------------------------------
BeanPostProcessor implementation that autowires annotated fields, setter methods, and arbitrary config methods. Such members to be injected are detected through annotations: by default, Spring's @Autowired and @Value annotations.
这边是说,对带注释的字段、setter方法和任意配置方法的BeanPostProcessor的实现。这些要注入的成员是通过注释检测到的,默认情况下,需要使用Spring的@Autowired和@Value注释。
Also supports JSR-330's @Inject annotation, if available, as a direct alternative to Spring's own @Autowired.
这边就是说这个也支持JSR-330这样标准的注解。下面是使用的方法和使用在哪个地方
Autowired Constructors
用在构造方法上
Only one constructor of any given bean class may declare this annotation with the 'required' attribute set to true, indicating the constructor to autowire when used as a Spring bean. Furthermore, if the 'required' attribute is set to true, only a single constructor may be annotated with @Autowired. If multiple non-required constructors declare the annotation, they will be considered as candidates for autowiring. The constructor with the greatest number of dependencies that can be satisfied by matching beans in the Spring container will be chosen. If none of the candidates can be satisfied, then a primary/default constructor (if present) will be used. If a class only declares a single constructor to begin with, it will always be used, even if not annotated. An annotated constructor does not have to be public.
上面主要是说用在构造方法上只能声明一个并只有一个被使用,最后也声明required的注解,如果有多个构造方法被注解,则spring容器会有自己的规则选一个,如果按规则没有选出则使用默认或主构造函数,如果存在的话。假设只有一个构造函数,即使没有被注解声明也会被使用。带注解的构造函数不一定要是公共的。
Autowired Fields
注解在字段上
Fields are injected right after construction of a bean, before any config methods are invoked. Such a config field does not have to be public.
字段是在bean构造之后、调用任何配置方法之前注入的。这样的配置字段不必是公共的。
Autowired Methods
注解在方法上
Config methods may have an arbitrary name and any number of arguments; each of those arguments will be autowired with a matching bean in the Spring container. Bean property setter methods are effectively just a special case of such a general config method. Config methods do not have to be public.
配置方法可以有任意的名称和任意数量的参数;这些参数中的每一个都将与Spring容器中的匹配bean自动连接。Bean属性设置方法实际上只是这种通用配置方法的一种特殊情况。配置方法不必是公共的。
Annotation Config vs. XML Config
注解在配置上如 xml配置
A default AutowiredAnnotationBeanPostProcessor will be registered by the "context:annotation-config" and "context:component-scan" XML tags. Remove or turn off the default annotation configuration there if you intend to specify a custom AutowiredAnnotationBeanPostProcessor bean definition.
NOTE: Annotation injection will be performed before XML injection; thus the latter configuration will override the former for properties wired through both approaches.
默认的AutowiredAnnotationBeanPostProcessor将被“context:annotation-config”和“context:component-scan”XML标记注册。如果您打算指定一个自定义的AutowiredAnnotationBeanPostProcessor bean定义,请删除或关闭默认的注释配置。
值得注意的是:注释注入将在XML注入之前执行;因此,对于通过两种方法连接的属性,后一种配置将覆盖前一种配置。(这下明白了xml配置中context:annotation-config和context:component-scan的作用了吧)
@Lookup Methods
In addition to regular injection points as discussed above, this post-processor also handles Spring's @Lookup annotation which identifies lookup methods to be replaced by the container at runtime. This is essentially a type-safe version of getBean(Class, args) and getBean(String, args). See @Lookup's javadoc for details.
除了上面讨论的常规注入点之外,这个后处理器还处理Spring的@Lookup注释,它标识了在运行时被容器替换的查找方法。这本质上是getBean(Class, args)和getBean(String, args)的类型安全版本。详情请参阅@Lookup的javadoc。(这个小编在实际中并没有怎么使用过,可以尝试一下)
通过以上的讲解大致可以知道internalAutowiredAnnotationProcessor所有的作用了,其实这边阅读源码好处多多。也可知道很多问题。
这个类的主要源码
public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor,
MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
protected final Log logger = LogFactory.getLog(getClass());
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
private String requiredParameterName = "required";
private boolean requiredParameterValue = true;
private int order = Ordered.LOWEST_PRECEDENCE - 2;
@Nullable
private ConfigurableListableBeanFactory beanFactory;
private final Set<String> lookupMethodsChecked = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache = new ConcurrentHashMap<>(256);
private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);
/**
* Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
* standard {@link Autowired @Autowired} and {@link Value @Value} annotations.
* Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
* if available.
*/
@SuppressWarnings("unchecked")
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
//后置处理合并beanDefinition 这个方法里面的私有方法自行观看
//主要找到注解的方法字段等等,然后属性注入
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
}
接着我们回过头来继续看构造方法
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
this()做了很多准备工作,那接下来的register(componentClasses);,其实就是将我们传入的类变成beanDefiniton并注入到beanFactory中,然后就可以refresh了
refresh方法特别特别重要,这里先不表,等小编融汇贯通之后,继续博客,请继续关注。
这篇文章主要讲了一个非常重要的概念beanDefiniton,小编这里用一个示例,慢慢深挖底层原理,不清楚小编有没有和大家讲清楚。这边注入了我们自己所编写的类后,然后根据这个类做了一系列工作,比方说spring要扫描哪些包了,注入哪些类等等。后期会详细描述。谢谢!如果有什么错误的地方也请各位指出,和小编一起学习spring源码啊。