美文网首页java学习笔记
Spring学习笔记(1):Spring基础及Bean注册

Spring学习笔记(1):Spring基础及Bean注册

作者: 小飞飞6号 | 来源:发表于2020-03-04 01:51 被阅读0次

Spring体系结构

1. spring为什么流行:
    a. spring专注于做两件事情 IOC( 控制反转) 和 AOP(面向切面)
    b. spring的原则是不重新造轮子,通过对现有的比较好的解决方案提供支持和接入。
    c. spring的扩展思想都是通过实现提供的接口,然后把这些接口注册到bean容器中,然后spring就会根据这些bean实现的接口去扩展某些spring的功能。例如我们经常使用的SpringContextUtils
2. Spting 7 大模块 
    a. Spring Core:即,Spring核心,它是框架最基础的部分,提供IOC和依赖注入特性
    b. Spring Context:即,Spring上下文容器,它是BeanFactory功能加强的一个子接口
    c. Spring Web:它提供Web应用开发的支持
    d. Spring MVC:它针对Web应用中MVC思想的实现
    e. Spring DAO:提供对JDBC抽象层,简化了JDBC编码,同时,编码更具有健壮性。
    f. Spring ORM:它支持用于流行的ORM框架的整合,比如:Spring + Hibernate、Spring + iBatis、Spring + JDO的整合等等。
    g. Spring AOP:AOP即,面向切面编程,它提供了与AOP联盟兼容的编程实现

Spring入门使用

1. 上下文
    a. ClassPathXmlApplicationContext 加载xml配置文件
    b. AnnotationConfigApplicationContext 加载注解配置类 手动使用的时候整个spring都是从这里开始(有空再研究tomcat启动war包的时候的启动点)

@Configuration

1. @ComponentScan 对指定路径下的文件进行注解配置扫描
    a. Value="包名"
    b. includeFilter={数组项1,数组项2},需要在同级别里同时设置useDefaultFilters=false
        i. 每一个数组项是@Filter(type=xxx,,classes={xxx,xxx})
            1) 当type=FilterType.CUSTOM,代表自定义类,该自定义类需要实现TypeFilter接口,可以在match方法中根据一些java逻辑去判断类要不要进行加载(见右图1)
    c. excludeFilter={数组项1,数组项2},需要设置useDefaultFilters=true
        i. 数组项同上
    d. useDefaultFilters:默认true为全集,false为空集,全集时exclude,空集时include
2. @Scope 指定bean为例与多例,默认单例
3. @Lazy 例子在cap4 懒加载在获取bean的时候才初始化(那标记在@Autowired注入呢?)
图1

类注册

1. @Bean 
    a. 默认id为方法名
2. @Component以及其扩展
    a. 默认id为完整包类名
3.  @Conditional条件注册bean,使用在@Bean的注解上,代表对该Bean进行一次判断
    a. 选择性地注入一些bean,例如区分linux和win平台
        i. Filter的type=CUSTOM应该也能做到同样的事情,但是控制的粒度不一样
    b. 使用方法@Conditional(实现Conditional接口的类.class)
    c. 使用-Dos.name=linux 可以把os.name=linux覆盖虚拟机的环境变量中
4. @Import 快速给容器导入一个组件(区别于@Bean和@Component)
    a. @Import({Xxx.class}) 加载一个类,可包括第三方类
        i. 那只能使用默认构造器?
        ii. 这么想不还是@Bean更好用吗
    b. 与@Bean的区别
        i. @Import导入的类的默认id是类全称,@Bena为方法名
    c. 当@Import中注册的类实现了ImportSelector接口时,这个接口返回的String[]里包含对应的类也会被当成bean注注册,数组的内容为需要注册的类的全类名。
    d. 当@Import中注册的类实现了ImportBeanDefinitonRegistrar接口:
        i. 可以在处理的时候,通过registry对象获取已经注册的bean,可以更加灵活地通过条件判断来注册bean,例如想要判断同时有猫跟狗的时候才注册老鼠bean。
        ii. 当判断好需要注册的时候,也是通过registry.registerBeanDefinition("bienID",RootBeanDefinition类型的封装类)主动放入到bean的容器中(Spring的IOC容器本质上就是一个map<String,RootBeanDefinition>),通过主动实例化再封装成RootBeanDefinition包装类,再给ImportBeanDefinitonRegistrar注册
5. FactoryBean 一个泛形接口,也可以灵活地控制任意一个类的创建过程
    a. 可以把java实例通过FactoryBean注入到容器中,实现以下方法
        i. getObject
        ii. getObjectType
        iii. isSingleton
    b. 实现这个接口以后,要把这个实现类也当作一个普通bean注册到容器中,当我们获取bean时,Spring会判断取出的bean是否为FactoryBean子类,若true则使用该BeanFactory的getObject(),构造一个类型为getObjectType的bean,并缓存且赶回该bean(关键方法:org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean)。换言之就是使用FactoryBean生成的Bean,替代了原来Factory的位置。这时候使用id获取bean后得到的就是与泛型一致的实例。
    c. 想要获取FactoryBean的实例本身,需要在beanID前面加上符号“&”
    d. 很重要的一个类,与aop和processor相关
6. FactoryBean 和 BeanFactory有什么区别(这个定义好像有点疑问)
    a. FactoryBean是一种注册机制,可以把Bean通过FactoryBean注入到容器中
    b. BeanFactory 从我们的容器中获取实例化后的Bean

关于最后的FactoryBean,其实Spring的源码中就有很多类似这样的注解来引导我们读懂spring,挺好的。


image

能力有限,如果我的笔记中有问题,请大佬不吝指出,加油!

最后上点源码

org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance

/**
     * Get the object for the given bean instance, either the bean
     * instance itself or its created object in case of a FactoryBean.
     * @param beanInstance the shared bean instance
     * @param name name that may include factory dereference prefix
     * @param beanName the canonical bean name
     * @param mbd the merged bean definition
     * @return the object to expose for the bean
     */
    protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

        // Don't let calling code try to dereference the factory if the bean isn't a factory.
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
            }
            if (mbd != null) {
                mbd.isFactoryBean = true;
            }
            return beanInstance;
        }

        // Now we have the bean instance, which may be a normal bean or a FactoryBean.
        // If it's a FactoryBean, we use it to create a bean instance, unless the
        // caller actually wants a reference to the factory.
        if (!(beanInstance instanceof FactoryBean)) {
            return beanInstance;
        }

        Object object = null;
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        else {
            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());
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }

org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean

/**
    /**
     * Obtain an object to expose from the given FactoryBean.
     * @param factory the FactoryBean instance
     * @param beanName the name of the bean
     * @param shouldPostProcess whether the bean is subject to post-processing
     * @return the object obtained from the FactoryBean
     * @throws BeanCreationException if FactoryBean object creation failed
     * @see org.springframework.beans.factory.FactoryBean#getObject()
     */
    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);
                    // Only post-process and store if not put there already during getObject() call above
                    // (e.g. because of circular reference processing triggered by custom getBean calls)
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    if (alreadyThere != null) {
                        object = alreadyThere;
                    }
                    else {
                        if (shouldPostProcess) {
                            if (isSingletonCurrentlyInCreation(beanName)) {
                                // Temporarily return non-post-processed object, not storing it yet..
                                return object;
                            }
                            beforeSingletonCreation(beanName);
                            try {
                                object = postProcessObjectFromFactoryBean(object, beanName);
                            }
                            catch (Throwable ex) {
                                throw new BeanCreationException(beanName,
                                        "Post-processing of FactoryBean's singleton object failed", ex);
                            }
                            finally {
                                afterSingletonCreation(beanName);
                            }
                        }
                        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;
        }
    }

相关文章

网友评论

    本文标题:Spring学习笔记(1):Spring基础及Bean注册

    本文链接:https://www.haomeiwen.com/subject/ldwjlhtx.html