Spring原理学习

2020-03-26  本文已影响0人  ccccaixiaohao

1.spring ioc 原理

a.详细原理分析:https://www.cnblogs.com/ITtangtang/p/3978349.html?clicktime=1583239891&enterid=1583239891#a4

b.粗略原理

    bean注册:
            1.Spring IoC容器根据定位的Bean定义资源文件,将其加载读入并转换成为Document对象过程完成。
             2.经过对Spring Bean定义资源文件转换的Document对象中的元素层层解析,Spring IoC现在已经将XML形式定义的Bean定义资源文件转换为Spring IoC所识别的数据结构——BeanDefinition。
              3.BeanDefinition注册过程就是在 IOC 容器内部维护的一个HashMap 来保存得到的 BeanDefinition 的过程。
     依赖注入:
           时机:
                 (1).用户第一次通过getBean方法向IoC容索要Bean时,IoC容器触发依赖注入。

              (2).当用户在Bean定义资源中为<Bean>元素配置了lazy-init属性,即让容器在解析注册Bean定义时进行预实例化,触发依赖注入。
    对使用工厂方法和自动装配特性的Bean的实例化相当比较清楚,调用相应的工厂方法或者参数匹配的构造方法即可完成实例化对象的工作,但是对于我们最常使用的默认无参构造方法就需要使用相应的初始化策略(JDK的反射机制或者CGLIB)来进行初始化。

在Spring中,有两个很容易混淆的类:BeanFactory和FactoryBean。
BeanFactory:Bean工厂,是一个工厂(Factory),我们Spring IoC容器的最顶层接口就是这个BeanFactory,它的作用是管理Bean,即实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

FactoryBean:工厂Bean,是一个Bean,作用是产生其他bean实例。通常情况下,这种bean没有什么特别的要求,仅需要提供一个工厂方法,该方法用来返回其他bean实例。通常情况下,bean无须自己实现工厂模式,Spring容器担任工厂角色;但少数情况下,容器中的bean本身就是工厂,其作用是产生其它bean实例。

当用户使用容器本身时,可以使用转义字符”&”来得到FactoryBean本身,以区别通过FactoryBean产生的实例对象和FactoryBean对象本身。在BeanFactory中通过如下代码定义了该转义字符:

StringFACTORY_BEAN_PREFIX = "&";

如果myJndiObject是一个FactoryBean,则使用&myJndiObject得到的是myJndiObject对象,而不是myJndiObject产生出来的对象。

2.Springboot原理

1.参考

https://www.jianshu.com/p/464d04c36fb1
https://cloud.tencent.com/developer/article/1449134

2.粗略原理

@SpringBootApplicationg有三个主要注解


image.png
1.@SpringBootConfiguration

其内部主要注解为@Configuration
其作用就是注册为配置类,扫描其中@Bean注解添加到ioc容器中相当于使用xml的方式进行bean注册。

2.@ComponentScan

该注解负责扫描包中的类似@Component,@Controller等注册到ioc容器中。

3.@EnableAutoConfiguration

其中包括@AutoConfigurationPakage和@Import(AutoConfigurationImportSelector.class)
@AutoConfigurationPakage它其实返回了当前主程序类的 同级以及子级的包组件
AutoConfigurationImportSelector这个类继承了 DeferredImportSelector 继承了 ImportSelector,其中selectImports方法会从META-INF/spring.factories外部文件扫描内容,以键值对的形式将用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。


image.png
image.png

3.Spring Aop原理

1.参考

https://blog.csdn.net/weixin_40160543/article/details/92010760
https://www.cnblogs.com/liuyk-code/p/9886033.html
http://www.pianshen.com/article/4914369461/
https://www.jianshu.com/p/b6d3e5a0c7e2

2.粗略原理

1.aop配置类向ioc容器注册
AnnotationAwareAspectJAutoProxyCreator
2.获取容器中的bean对象,注册后置处理器,将增强转换为拦截器,组成拦截器链
3.遍历所有bean对象,在创建前判断是否需要增强。如果需要就创建bean的代理对象。
4.返回普通的bean对象和代理对象。

4.myBatis原理

1.代理实现

mybatis通过Proxy类将mapper接口解析并放回代理对象
sqlSession原理:

package com.cwh.XiaohaoMybatis;
import java.lang.reflect.Proxy;

public class XiaohaoSession {

    public static Object getMapper(Class clazz){
        Class[] classes = new Class[]{clazz};
        Object objecy = Proxy.newProxyInstance(XiaohaoSession.class.getClassLoader(), classes, new XiaohaoInvocationHandler());
        return objecy;
    }

}

具体实现sql

package com.cwh.XiaohaoMybatis;

import org.apache.ibatis.annotations.Select;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class XiaohaoInvocationHandler implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Select annotation = method.getAnnotation(Select.class);
        if(null!=annotation){
            System.out.println("sql---"+annotation.value()[0]);
        }
        return null;
    }
}

2.与spring结合

mybatis需要将代理对象交给ioc容器
借助factoryBean可以将放回每一个mapper接口的代理对象

package com.cwh.XiaohaoMybatis;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;


public class XiaohaoMaperFactoryBean implements FactoryBean {
    Class mapperClass;

    XiaohaoMaperFactoryBean(Class mapperClass){
        this.mapperClass = mapperClass;
    }

    @Override
    public Object getObject() throws Exception {
        return XiaohaoSession.getMapper(mapperClass);
    }

    @Override
    public Class<?> getObjectType() {
        return mapperClass;
    }
}

借助BeanDefinitionRegistrar可以将每个由factoryBean产生的代理对象注册到ioc中

package com.cwh.XiaohaoMybatis;

import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

public class XiaohaoBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(XiaohaoMaperFactoryBean.class);
        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
        //可以循环注册出每个mapper
        beanDefinition.getConstructorArgumentValues().addGenericArgumentValue("com.cwh.XiaohaoMybatis.XiaohaoMapper");
        beanDefinitionRegistry.registerBeanDefinition("XiaoHaoMapper",beanDefinition);


    }
}

需要在配置类中告知spring

package com.cwh.XiaohaoMybatis;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
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
@ComponentScan("com.cwh")
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
@Import(XiaohaoBeanDefinitionRegistrar.class)
public class SpringConfig {
    

}

主测试类

public static void main(String[] args) {
        AnnotationConfigApplicationContext ac  = new AnnotationConfigApplicationContext(SpringConfig.class);
        XiaohaoServlet xiaohaoServlet = ac.getBean(XiaohaoServlet.class);
        System.out.println(xiaohaoServlet);
        xiaohaoServlet.queryAll();

    }
上一篇 下一篇

猜你喜欢

热点阅读