Spring
注解配置启动
AnnotationConfigAppliactionContext ao = new AnnotationConfigApplicationContext(Appconfig.class);
Appconfig 类上加 @Configuration @ComponentScan(“扫描的包路径”)
实例化过程:
this() – 创建bean工厂 new DefaultListableBeanFactory()
register(annotatedClasses(传入的class类));
- 把传入的类 定义成BeanDefinition放入 beanDefinitionMap,把所有class放入 beanDefinitionNames list中
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
servlet WebApplicationContext 子容器可以引用到父容器的对象存放:services, Repositories datasources
存放: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都不指定,事物先执行
解析完切面为什么加入到缓存
重复使用