Spring_IOC

原文:小马哥讲Spring核心编程思想课程

InversionOfControl Martin Fowler

IOC主要实现策略

1.Using a service locator pattern(服务定位模式)
通过JNDI获取JavaEE/EJB组件…
2.依赖注入
3.上下文的依赖查询
4.模板方法的设计模式
5.策略模式
**《Expert One-on-One J2EE Development without EJB》**Spring的原作者

IOC容器的职责

1.实现与执行的任务要产生解耦
2.关注于你的设计上的最终目标
3.要释放这个模块
4.当模块变更的时候,它的副作用
5.好莱坞原则。

1.通用职责
2.依赖处理:依赖查找和依赖注入
3.生命周期管理:容器,托管的资源(Java Beans 或其他资源)
4.配置:容器,外部化配置,托管的资源(Java Beans或其他资源 )

轻量级IOC容器

1.可管理应用代码(容器可以管理代码运行,启停,声明周期等)
2.快速启动
3.容器不需要特殊的配置
4.容器可以达到小内存,不需要依赖过多的API

好处:
1.释放掉容器(释放聚式容器,实现和代码解耦)
2.实现最大化的代码复用
3.更大程度上的面向对象
4.更大化的一个产品化(运维管理工具,配套措施等)
5.更好的可测试性

Java Beans作为IOC容器

特性:
依赖查找
生命周期管理
配置元信息
事件
自定义
资源管理
持久化

BeanInfo:描述bean信息的类

BeanInfo beanInfo = Introspector.getBeanInfo(Person.class, Object.class);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
//BeanInfo中拥有描述一个类的很多方法,比如获得字段名称,方法名等等...

在这里插入图片描述

依赖查找&依赖注入

一个是查找,一个是注入(绑定)
手动获取

构造器注入&&=Setter注入

1.构造器注入
手动模式
XML资源配置元信息
在这里插入图片描述
JAVA注解配置元信息
@Bean
API配置元信息
在这里插入图片描述

自动模式
constructor
在这里插入图片描述

Setter注入的优点:
1.JavaBean的属性通常对IDE支持得比较好
2.JavaBean的属性通常是一个自文档的格式(不需要过多的文档进行说明,因为方法名就知道要做什么)
3.JavaBean的属性编辑器机制对于类型转换(It’s possible to use thre standard JavaBean property-editor machinery for type conversions if necessary)
setValue() -->setPropertyEditorClass()
4.更多存在的JavaBean能够在JavaBean里面去使用而不需要任何的修改(BeanContext)
5.可配置化以及对Bean更容易进行管理
6.Setter可在对象里面有个默认值

Setter注入的缺点:
1.没有锲约去约束设置依赖的先后顺序,如构造器的参数是有前后顺序的,即bean的初始化有顺序
2.Setter是根据需求来调用的

构造器的优势:
1.属性可设置为final
2.bean过多的时候,可以减少代码
3.防止属性被过多的修改(对象确定后更应该少修改)
4.构造器注入是绝对不允许循环依赖存在的,但setter没有这样的要求

Spring IOC依赖查找

1.按照名字查找
实时查找:直接ApplicationContext.getBean();
延迟查找
在这里插入图片描述

2.按照类型查找
单一类型
在这里插入图片描述
集合类型
ListableBeanFactory
在这里插入图片描述
ListableBeanFactory是通过名称或类型来查找一个bean集合
->根据Bean类型查找
–>获取同类型Bean名称列表
—>getBeanNamesForType(Class)
—>Spring 4.2 getBeanNamesForType(ResolveableType)
–>获取同类型Bean实例列表
—>getBeansOfType(Class) 以及重载方法
->根据注解类型查找
–>获取标注类型Bean名称列表
—>getBeanNamesForAnnotation(Class<? extends Annotation>) //当前类及子类
–>获取标注类型Bean实例列表
—>getBeanWithAnnotation(Class<? extends Annotation>)
–>获取指定名称+标注类型Bean实例列表
—>findAnnotationOnBean(String,Class<? extends Annotation>)

使用Bean 的名称判断Bean是否存在,这样可以避免Bean过早的初始化。

Bean的延迟查找:
getBeanProvider(Class)
在这里插入图片描述
getBeanProvider(ResolvableType)

3.根据Bean名称+类型查找
在这里插入图片描述
4.按照注解查找(反射标签)
在这里插入图片描述在这里插入图片描述

BeanFactory&FactoryBean&ObjectFctory
这里梳理一下三者的区别。
BeanFctory:顾名思义就是一个容器,用来获得Bean的。
FactoryBean:如果一个对象实现了FactoryBean 那么通过它get出来的对象实际是factoryBean.getObject() 得到的对象,如果想得到FactoryBean必须通过在 ‘&’ + beanName 的方式获取。FactoryBean着重于自定义创建对象过程,由BeanFactory通过FactoryBean来获取目标对象,而如果是isSingleton返回true的话。spring会利用单例缓存来缓存通过FactoryBean创建的对象。
在这里插入图片描述
ObjectFactory:则只是一个普通的对象工厂接口。将创建对象的步骤封装到ObjectFactory中 交给自定义的Scope来选择是否需要创建对象来灵活的实现scope。此外在将给依赖注入列表注册一个ObjectFactory类型的对象,在注入过程中会调用objectFactory.getObject()来创建目标对象注入进去。

5.层次性依赖查找
查找接口-HierachicalBeanFactory
子接口:ConfigurableBeanFactory
子子接口:ConfigurableListableBeanFactory
在这里插入图片描述
双亲BeanFctory:getParentBeanFctory()
在这里插入图片描述

层次性查找
->根据Bean名称查找:基于containsLocalBean方法实现
->根据Bean类型查找实例列表:单一:BeanFactoryUtils#beanOfType。
-> 集合:BeanFctoryUtils#beansOfTypeIncludingAncestors
在这里插入图片描述

->根据Java注解查找名称列表:BeanFactoryUtils#beanNamesForTypeIncludingAncestors

6.延迟依赖查找
1.ObjectFactory
2.ObjectProvider //extends ObjectFactory
在这里插入图片描述

7.安全依赖查找
在这里插入图片描述
单一类型
在这里插入图片描述
集合类型
在这里插入图片描述

DefaultListableBeanFactory impl… ConfigurableListableBeanFactory
在这里插入图片描述
层次性依赖查找的安全性取决于其扩展的单一或集合类型的BeanFactory接口
当Bean不存在的时候会抛出异常。

内建可查找的依赖

内建的依赖配置在AnnotationConfigUtils中
AbstractApplicationContext内建可查找的依赖

在这里插入图片描述

1.environment
可通过修改属性来改变行为,如profile在不同的环境会有不同的配置
2.systemProperties
获取系统属性,路径等

注解驱动Spring应用上下文内建可查找的依赖
在这里插入图片描述

在这里插入图片描述

依赖查找的来源

在这里插入图片描述

Spring IOC依赖注入

The Spring container can autowire relationships between collaborating beans.You can let Spring resolve collaborators (other beans) automatically for your bean by inspectiong the contents of the AppliacationContext.
有点:
Autowiring can significantly reduce the need to specify properties or constructor arguments.
Autowiring can update a configuration as your objects evolve.

在这里插入图片描述
在这里插入图片描述

Autowiring的不足
1.精确依赖,缺乏精确,因为是猜测关联的。
2.不能绑定简单类型,String。但是可以通过@Value注入
3.难以在工具类上面呈现。没有运行状态来提前预判。
4.如果存在多个Bean的定义,绑定的时候会报错。

1.Setter 方法注入
手动模式:
XML资源配置元信息
在这里插入图片描述
在这里插入图片描述

Java注解配置元信息
在这里插入图片描述
API配置元信息
在这里插入图片描述
底层实现,注册Bena以及依赖查找的核心
在这里插入图片描述

自动模式:
byName
在这里插入图片描述
byType
在这里插入图片描述

2.字段注入
手动模式
Java注解配置元信息
@Autowired:这个注解不会处理静态字段的
@Resource
@Inject

//不能处理静态字段的解决方法
private static OpenSearchProperties openSearchProperties;
@Resource(name = "openSearchProperties")
    public void setOpenSearchProperties(OpenSearchProperties openSearchProperties) {
        OpenSearchUtil.openSearchProperties = openSearchProperties;
    }

3.方法 注入

手动模式
Java注解配置元信息
@Autowired //可以注入方法里面的参数
@Resource
在这里插入图片描述

@Inject
@Bean

4.接口回调注入
在这里插入图片描述
在这里插入图片描述

5.基础类型注入

在这里插入图片描述

类型转换:Sting -> enum/Resource
在这里插入图片描述

在这里插入图片描述

6.集合类型注入
数据类型:原生类型,标量类型,常规类型,Spring类型
集合类型:Collection,Map
在这里插入图片描述

在这里插入图片描述

7.限定注入
使用注解@Qualifier限定
通过Bean名称限定
在这里插入图片描述

通过分组限定
给标注了@Qualifier的进行了区分
allUsers 只存在没有标注@Qualifier的User
在这里插入图片描述

自定义注解:
在这里插入图片描述

8.延迟依赖注入
使用API ObjectFactory延迟注入
单一类型
集合类型
使用API ObjectProvider延迟注入(推荐 安全)
单一类型
集合类型(bean有多个,就默认获得多个了)
以下的userObjectProvider可以forEach
在这里插入图片描述

@Inject注入
如果JSR-33存在于ClassPath中,复用AutowiredAnnotationBeanPostProcessor实现
AutowiredAnnotationBeanPostProcessor首先优先处理@Autowired,@Value 然后@Inject
链式存储Annotation
try catch住是因为如果存在则处理,不存在也不会报错。
在这里插入图片描述

1.根据Bean名称注入
中根据
2.根据Bean类型注入
单个Bean对象
集合Bean对象
在这里插入图片描述
3.注入容器内建Bean对象
在这里插入图片描述
可以直接获得BeanFactory,输出结果是它是一个DefaultListableBeanFactory。它和本身new 的ApplicationContect不是同一个。输出的BeanFactory也不是一个Bean。
在这里插入图片描述

所以依赖查找和依赖注入的东西不是同源的。
依赖的来源:
1.自定义的Bean。
2.依赖注入(内部的依赖,BeanFactory等)
3.容器内建的Bean。(applicationContext.getEnvironment())

4.注入非Bean对象
5.注入类型
实时注入
延迟注入

@Autowire注入过程

合并属性
MergreBeanDefinitionPostProcessor
意思就是父类的属性,子类会合并过来

class -> AutowiredAnnotationBeanPostProcessor
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		//递归取查找 当前类及父类
        InjectionMetadata metadata = this.findAutowiringMetadata(beanName, beanType, (PropertyValues)null);
        //检查配置
        metadata.checkConfigMembers(beanDefinition);
    }

1.元信息解析
DependencyDescriptor 依赖描述器:记录了注入的对象是关于哪个字段(字段名称,元信息等)

class -> InstantionAwareBeanPostProcessor
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
        InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);

        try {
            metadata.inject(bean, beanName, pvs);
            return pvs;
        } catch (BeanCreationException var6) {
            throw var6;
        } catch (Throwable var7) {
            throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);
        }
    }

2.依赖查找:依赖处理
3.依赖注入(字段,方法)

InstantiationAwareBeanPostProcessor.postProcessPropertie()调用了inject

AutowiredAnnotationBeanPostProcessor
这个类做了两个过程:依赖查找以及依赖注入

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            Field field = (Field)this.member;
            Object value;
            if (this.cached) {
                value = AutowiredAnnotationBeanPostProcessor.this.resolvedCachedArgument(beanName, this.cachedFieldValue);
            } else {
                DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
                desc.setContainingClass(bean.getClass());
                Set<String> autowiredBeanNames = new LinkedHashSet(1);
                Assert.state(AutowiredAnnotationBeanPostProcessor.this.beanFactory != null, "No BeanFactory available");
                TypeConverter typeConverter = AutowiredAnnotationBeanPostProcessor.this.beanFactory.getTypeConverter();

                try {
                	//依赖查找
                    value = AutowiredAnnotationBeanPostProcessor.this.beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
                } catch (BeansException var12) {
                    throw new UnsatisfiedDependencyException((String)null, beanName, new InjectionPoint(field), var12);
                }

                synchronized(this) {
                    if (!this.cached) {
                        if (value == null && !this.required) {
                            this.cachedFieldValue = null;
                        } else {
                            this.cachedFieldValue = desc;
                            AutowiredAnnotationBeanPostProcessor.this.registerDependentBeans(beanName, autowiredBeanNames);
                            if (autowiredBeanNames.size() == 1) {
                                String autowiredBeanName = (String)autowiredBeanNames.iterator().next();
                                if (AutowiredAnnotationBeanPostProcessor.this.beanFactory.containsBean(autowiredBeanName) && AutowiredAnnotationBeanPostProcessor.this.beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                    this.cachedFieldValue = new AutowiredAnnotationBeanPostProcessor.ShortcutDependencyDescriptor(desc, autowiredBeanName, field.getType());
                                }
                            }
                        }

                        this.cached = true;
                    }
                }
            }

            if (value != null) {
                ReflectionUtils.makeAccessible(field);
                //依赖注入过程
                field.set(bean, value);
            }

        }

JAVA通用注解注入原理

CommonAnnotationBeanPostProcessor
注入注解
1.javax.xml.ws.WebServiceRef
2.java.ejb.EJB
3.javax.annotation.Resource

生命周期注解
javax.annotation.PostConstruct
javax.annotation.PreDestory

在这里插入图片描述

自定义依赖注解注入

自定义注解
在这里插入图片描述

将自定义的注解加入到AutowiredAnnotaionBeanPostProcessor
在这里插入图片描述
或者
在这里插入图片描述

依赖处理过程

在这里插入图片描述

在这里插入图片描述

descriptor 里面包含了注入相关的一些元信息如:required eager filedName

@Nullable
    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    
        descriptor.initParameterNameDiscovery(this.getParameterNameDiscoverer());
        if (Optional.class == descriptor.getDependencyType()) {
            return this.createOptionalDependency(descriptor, requestingBeanName);
        } else if (ObjectFactory.class != descriptor.getDependencyType() && ObjectProvider.class != descriptor.getDependencyType()) {
            if (javaxInjectProviderClass == descriptor.getDependencyType()) {
                return (new DefaultListableBeanFactory.Jsr330Factory()).createDependencyProvider(descriptor, requestingBeanName);
            } else {
                Object result = this.getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
                if (result == null) {
                    result = this.doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
                }

                return result;
            }
        } else {
            return new DefaultListableBeanFactory.DependencyObjectProvider(descriptor, requestingBeanName);
        }
    }

依赖注入的来源

比依赖查找多一个非Spring容易管理对象,不能用于依赖查找,只能用于依赖注入。
可通过prepareBwanFactory的registerResolveableDependency进行注入
在这里插入图片描述

registerResolveableDependency
自动绑定的时候找到
注册非托管的对象
在这里插入图片描述

Spring容器管理和游离对象

在这里插入图片描述

Spring BeanDefinition 作为依赖来源

元数据:BeanDefinition
注册:BeanDefinitionRegisger#registerBeanDefinition
类型:延迟和非延迟
顺序:Bean生命周期顺序按照注册顺序

注册BeanDefinition

    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");
        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
            	//1.校验
                ((AbstractBeanDefinition)beanDefinition).validate();
            } catch (BeanDefinitionValidationException var8) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);
            }
        }
		//2.获取是否存在
        BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
        if (existingDefinition != null) {
        //3.判断是不是可以被overwrite 默认是true
            if (!this.isAllowBeanDefinitionOverriding()) {
                throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
            }
			
            if (existingDefinition.getRole() < beanDefinition.getRole()) {
                if (this.logger.isInfoEnabled()) {
                    this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
                }
            } else if (!beanDefinition.equals(existingDefinition)) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
                }
            } else if (this.logger.isTraceEnabled()) {
                this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
            }
			
            this.beanDefinitionMap.put(beanName, beanDefinition);
        } else {
            if (this.hasBeanCreationStarted()) {
                Map var4 = this.beanDefinitionMap;
                synchronized(this.beanDefinitionMap) {
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    //注入名字 是个List 所以带有顺序
                    this.beanDefinitionNames = updatedDefinitions;
                    this.removeManualSingletonName(beanName);
                }
            } else {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                this.removeManualSingletonName(beanName);
            }

            this.frozenBeanDefinitionNames = null;
        }

        if (existingDefinition != null || this.containsSingleton(beanName)) {
            this.resetBeanDefinition(beanName);
        }

    }

单例对象作为依赖来源

来源:外部普通Java对象(不一定是POJO)
注册:SingletonBeanRegistry#registerSingleton
限制:无生命周期管理,无法实现言辞和初始化Bean
可用于依赖查找以及依赖注入

map存储
在这里插入图片描述
在查找Bean的时候,Singleton和BeanDefinition有异曲同工之处。
Singleton是查到就返回,所以没有声明周期的管理。
而BeanDefinitoin则需要做生命周期的管理

在这里插入图片描述
AbstractBeanFactory


    protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
        String beanName = this.transformedBeanName(name);
        Object sharedInstance = this.getSingleton(beanName);
        Object bean;
        if (sharedInstance != null && args == null) {
            if (this.logger.isTraceEnabled()) {
                if (this.isSingletonCurrentlyInCreation(beanName)) {
                    this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
                } else {
                    this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }

            bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        } else {
            if (this.isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            BeanFactory parentBeanFactory = this.getParentBeanFactory();
            if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
                String nameToLookup = this.originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
                }

                if (args != null) {
                    return parentBeanFactory.getBean(nameToLookup, args);
                }

                if (requiredType != null) {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }

                return parentBeanFactory.getBean(nameToLookup);
            }

            if (!typeCheckOnly) {
                this.markBeanAsCreated(beanName);
            }

            try {
                RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                this.checkMergedBeanDefinition(mbd, beanName, args);
                String[] dependsOn = mbd.getDependsOn();
                String[] var11;
                if (dependsOn != null) {
                    var11 = dependsOn;
                    int var12 = dependsOn.length;

                    for(int var13 = 0; var13 < var12; ++var13) {
                        String dep = var11[var13];
                        if (this.isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }

                        this.registerDependentBean(dep, beanName);

                        try {
                            this.getBean(dep);
                        } catch (NoSuchBeanDefinitionException var24) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
                        }
                    }
                }

                if (mbd.isSingleton()) {
                    sharedInstance = this.getSingleton(beanName, () -> {
                        try {
                            return this.createBean(beanName, mbd, args);
                        } catch (BeansException var5) {
                            this.destroySingleton(beanName);
                            throw var5;
                        }
                    });
                    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                } else if (mbd.isPrototype()) {
                    var11 = null;

                    Object prototypeInstance;
                    try {
                        this.beforePrototypeCreation(beanName);
                        prototypeInstance = this.createBean(beanName, mbd, args);
                    } finally {
                        this.afterPrototypeCreation(beanName);
                    }

                    bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                } else {
                    String scopeName = mbd.getScope();
                    Scope scope = (Scope)this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }

                    try {
                        Object scopedInstance = scope.get(beanName, () -> {
                            this.beforePrototypeCreation(beanName);

                            Object var4;
                            try {
                                var4 = this.createBean(beanName, mbd, args);
                            } finally {
                                this.afterPrototypeCreation(beanName);
                            }

                            return var4;
                        });
                        bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    } catch (IllegalStateException var23) {
                        throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var23);
                    }
                }
            } catch (BeansException var26) {
                this.cleanupAfterBeanCreationFailure(beanName);
                throw var26;
            }
        }

        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = this.getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                } else {
                    return convertedBean;
                }
            } catch (TypeMismatchException var25) {
                if (this.logger.isTraceEnabled()) {
                    this.logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var25);
                }

                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        } else {
            return bean;
        }
    }

非Spring容器管理对象作为依赖来源

注册:ConfigurableListableBeanFactory#registerResolvableDenpendency
限制:无生命周期管理,无法实现延迟初始化Bean,无法通过依赖查找

invokeBeanFactoryPostProcessors(beanFactory)
在这里插入图片描述

外部化配置作为依赖来源

属性配置脱离于我当前的代码
类型:非常规Spring对象依赖来源
限制:无生命周期管理,无法实现延迟初始化Bean,无法通过依赖查找

配置文件有值,则为必须,没有默认value种兜底

在这里插入图片描述
在这里插入图片描述

Spring IOC 配置元信息

1.Bean定义配置
基于XML文件
基于Properties文件
基于Java注解
基于Java API
2.IOC容器配置
基于XML文件
基于Java注解
基于Java API
3.外部化属性配置
基于Java注解

BeanFactory和ApplicaiotnContext谁才是IOC容器?

BeanFactory是Spring底层IOC容器
ApplicationContext是具备应用特性的BeanFactory超集

BeanFactory interface provides an advanced configuraion mechanism capable of managing any type of objectl.
BeanFctory接口提供了一些很高级的机制,能够来管理这些对象

ApplicaiotnContext是BeanFactory的子接口。它提供以下一些特性:
1.简化了一些整合(SpringAOP的整合)
2. 消息资源的一个处理
3. 事件的发布
4. 应用级别的一些上下文

BeanFactory配置了一个基础的框架,并且是以一个基本的功能的集合。

ClassPathXmlApplicationContext  -> AbstractXmlApplicationContext -> AbstractRefreshableConfigApplicationContext ->
AbstractRefreshableApplicationContext -> AbstractApplicationContext -> ConfigurableApplicationContext -> ApplicationContext
-> ...-> BeanFactory

在上面的一些继承和实现之中。
AbstractRefreshableApplicationContext 持有了  private DefaultListableBeanFactory beanFactory;。
里面有一个getBeanFactory() 方法。
所以它既是继承又是组合的方式持有BeanFactory。

不使用Application也能加载Bean
在这里插入图片描述

AnnotationConfigApplicationContext 注解配置上下文。
在这里插入图片描述

Spring 应用上下文

1.IOC容器
2.面向切面
3.配置元信息
4.资源管理
5.事件
6.国际化
7.注解
8.Environment抽象
配置
外部化配置

Spring IOC 容器生命周期

启动
ApplicationContext.refresh(){
1.加锁:因为容器在哪里都能被使用,防止多线程出现线程安全问题。
2.创建BeanFactory,并且进行初步的初始化。
3.BeanFactory加入一些内建的Bean对象或者Bean依赖,以及一些内建的非Bean依赖。
4.BeanFactory的扩展点:invokeBeanFactoryPostProcessors(beanFactory);
5.对Bean的一些修改或者扩展registerBeanPostProcessors(beanFactory);
}

初始化的时候,自定义方法的先后顺序
1、init-method方法,初始化bean的时候执行,可以针对某个具体的bean进行配置。init-method需要在applicationContext.xml配置文档中bean的定义里头写明。例如:
这样,当TestBean在初始化的时候会执行TestBean中定义的init方法。

2、afterPropertiesSet方法,初始化bean的时候执行,可以针对某个具体的bean进行配置。afterPropertiesSet 必须实现 InitializingBean接口。实现 InitializingBean接口必须实现afterPropertiesSet方法。

3、BeanPostProcessor,针对所有Spring上下文中所有的bean,可以在配置文档applicationContext.xml中配置一个BeanPostProcessor,然后对所有的bean进行一个初始化之前和之后的代理。BeanPostProcessor接口中有两个方法: postProcessBeforeInitialization和postProcessAfterInitialization。 postProcessBeforeInitialization方法在bean初始化之前执行, postProcessAfterInitialization方法在bean初始化之后执行。

总之,afterPropertiesSet 和init-method之间的执行顺序是afterPropertiesSet 先执行,init-method 后执行。从BeanPostProcessor的作用,可以看出最先执行的是postProcessBeforeInitialization,然后是afterPropertiesSet,然后是init-method,然后是postProcessAfterInitialization。

运行

停止
1.this.startupShutDownMonitor
2.销毁所有的Bean
3.将BeanFactory关掉。
4.可以继承Application扩展onClose()方法。

备注

System.out 和 System.err 不在同一个输出流中,所以输出的信息不对称。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值