spring

Spring

注解配置启动

AnnotationConfigAppliactionContext ao = new AnnotationConfigApplicationContext(Appconfig.class);
Appconfig 类上加 @Configuration @ComponentScan(“扫描的包路径”)
实例化过程:

  1. this() – 创建bean工厂 new DefaultListableBeanFactory()

  2. register(annotatedClasses(传入的class类));

    • 把传入的类 定义成BeanDefinition放入 beanDefinitionMap,把所有class放入 beanDefinitionNames list中
  3. refresh()

    • invokeBeanFactoryPostProcessors();

      RootBeanDefinition -初始化bean定义,放入beanDefinitionMap
      在实例化bean的时候,spring提供了接口,可以让程序员来干预bean的初始化 
      **BeanFactoryPostProcessors**,bean工厂后置处理器,可以对放入beanDefinitionMap中的bean属性进行修改 ,比如懒加载,等等。。
      执行内置或者自定义的 beanFactoryPostProcessor实现
    • finishBeanFactoryInitialization(); 实例化bean

      循环beanDefinitionNames ,从beanDefinitionMap获取bean定义
      getBean : 从singletonObjects map 中获取单例bean或者在isSingletonCurrentlyInCareation set中存在 ( 创建中的bean会存入这里,解决循环依赖)
      不存在:创建对象,调用getSingleton()方法,把当前bean放入isSingletonCurrentlyInCareation 的set集合中,然后通过回调,调到createBean()方法
      createBean():resolveBeforeInstantion() 方法,在这里去解析标注了@Aspect的类,生成aop的切面对象(before,after),进行缓存
      doCreateBean(): 
      ----------------在createBeanIntance() 创建对象-----------------,
      在populateBean() 完成bean属性的注入,如@Autowired
      在initializeBean() 进行初始化
              初始化前,会先调用bean的后置处理器(**BeanPostProcessor**)的前置方法
              初始化:invokeInitMethods(),调用自定义的初始化方法
              初始化后:再次调用后置处理的的after方法,(aop的代理对象就是在此处生成)
      初始化完成后会把这个bean加入到 singletonObjects 单例缓存池的map中

      解析—调用构造器—-属性赋值–init ,在这期间后置处理器都会干预bean的初始化
      spring的9出后置处理器:使用bean的后置处理器来扩展功能
      · 没有调构造方法前:resolveBeforeInstantion()中调用,解析切面,事物切面
      · 在createBeanIntance()创建bean的时候推断用哪个构造函数去实例化
      · 预解析@Autowired
      · 解决循环依赖
      · populateBean()在给bean中属性赋值前,可以根据自己实现的后置处理器给属性复制
      · spring 填充属性到bean对象前
      · invokeInitMethods 前
      · invokeInitMethods 后,生成aop代理
      · 容器销毁时,调用
      bean作用域:
      singleyon(单例):ioc容器管理,只有一个
      prototype(原型):没次都从容器中get一个新的bean实例
      request(web):存在每个请求中,一个http请求创建一个新的
      session(http session共享的bean)
      globalSession(web )

  • spring支持循环依赖,但是bean必须是单例的

    后置处理器 实现BeanPostProcessor 干预bean的初始化过程

    在bean声明周期初始化前后执行

    spring 和spring MVC整合的时候会出现父子容器

    为了职责单一,在spring MVC配置文件中,有一个ContextLoaderListener 监听器,是来加载父容器,dispatcherServlet是初始化子容器
    root WebApplicationcontext
    存放:services, Repositories datasources
    servlet WebApplicationContext 子容器可以引用到父容器的对象
    存放:Controllers ViewResolvers HandlerMapping

IOC

this() :创建bean工厂 new DefaultListableBeanFactory()

AOP

给指定的类生成代理类
存放在什么地方:singletonObjects map中,单例缓存池
什么时候生成:
容器启动,调用refresh方法,
->finishBeanFactoryInitialization()
-> doGetBean()
-> getSingleton()
-> doCreateBean()
-> ininializeBean()
-> 在bean初始化后,调用后置处理器生成代理对象
@EnableAspectJAutoProxy 开启AOP,在这个注解里,通过@import导入了一个组件,AnnoationAwareAspectJCreator(切面生成器组件),这个组件最终实现了BeanPostProcessor后置处理器接口,切面生成是通过实现importBeanDifiniationRegister 来注册一个bean定义。

  • 什么时候去解析切面:

    在spring初始化创建bean的环节中(还没有调用bean的构造方法之前)去执行bean的后置处理器InstantiationAwareBeanPostProcessor中的postProcessorBeforeInstatiation方法进行处理。由于此时还没有生成目标对象(代理对象),所以该处理器只解析切面,并加入缓存
    解析切面:在后置处理器中解析所有的bean,拿到class对象,看对象上是否加了@Aspect注解,然后在拿到每个方法class.getMethod(),根据方法上的注解来生成相应的切面对象

    解析切面类中的注解生成对应的Advice对象

  • aop默认使用什么代理?
    如果@EnableAspectJAutoProxy(proxyTargetClass = false –默认false)时,如果代理类实现了接口,就用JDK动态代理,没有实现接口使用cglib代理
    如果@EnableAspectJAutoProxy(proxyTargetClass = true) 指定为true时,强制使用cglib代理

  • @EnableAspetAutoProxy(expostProxy = true 默认false) 暴露代理对象到当前的线程变量中
    通过以下调用,从线程变量中把代理对象取出来,通过代理对象调用,这样被调用的方法也会被增强
    AopContext.currentProxt().add();
    类似的还有事物方法,a调用b,然后b也会自动加上事物

  • 怎么指定切面优先级
    通过@order(1) 指定参数,参数越小,级别越高
    实现Ordered接口,重写order方法,原理一样
    如果不指定,最低级别,事物切面一样,如果一个方法即有切面,又有事物,order都不指定,事物先执行
    解析完切面为什么加入到缓存
    重复使用