Spring注解詳解


1.@Autowired
標注在方法,Spring容器創建當前對象,就會調用方法,完成賦值;方法使用的參數,自定義類型的值從ioc容器中獲取
自動裝配;
Spring利用依賴注入(DI),完成對IOC容器中中各個組件的依賴關系賦值;
1)、@Autowired:自動注入:
  A、默認優先按照類型去容器中找對應的組件:applicationContext.getBean(Person.class);找到就賦值
  B、如果找到多個相同類型的組件,再將屬性的名稱作為組件的id去容器中查找applicationContext.getBean("person")
  C、@Qualifier("person"):使用@Qualifier指定組件的進行裝配,不是屬性名
  D、自動裝配默認一定要將屬性賦值好,沒有就會報錯;可以使用@Autowired(required=false);
  E、@Primary:讓Spring進行自動裝配的時候,默認使用首選的bean;
  也可以繼續使用@Qualifier指定需要裝配的bean的名字
  

PersonService{
    @Autowired
    PersonDao personDao;
  }

  


2)、Spring還支持使用@Resource(JSR250)和@Inject(JSR330)[java規范的注解]
  @Resource:
  可以和@Autowired一樣實現自動裝配功能;默認是按照組件名稱進行裝配的;
  沒有能支持@Primary功能
  沒有支持@Autowired(reqiured=false);
  @Inject:
  需要導入javax.inject的包,和Autowired的功能一樣。沒有required=false的功能;
  @Autowired:Spring定義的; @Resource、@Inject都是java規范

  AutowiredAnnotationBeanPostProcessor:解析完成自動裝配功能;
3)、 @Autowired:可以使用在構造器,參數,方法,屬性上;都是從容器中獲取參數組件的值
  A、[標注在方法位置]:@Bean+方法參數;參數從容器中獲取;默認不寫@Autowired效果是一樣的;都能自動裝配
  B、[標在構造器上]:如果組件只有一個有參構造器,這個有參構造器的@Autowired可以省略,參數位置的組件還是可以自動從容器中獲取
  C、放在參數位置:
4)、自定義組件想要使用Spring容器底層的一些組件(ApplicationContext,BeanFactory,xxx);
  自定義組件實現xxxAware;在創建對象的時候,會調用接口規定的方法注入相關組件;Aware;
  把Spring底層一些組件注入到自定義的Bean中;
  xxxAware:功能使用xxxProcessor;
  ApplicationContextAware==》ApplicationContextAwareProcessor;

2.@Component
  默認加在ioc容器中的組件,容器啟動會調用無參構造器創建對象,再進行初始化賦值等操作【構造器要用的組件,都是從容器中獲取】
3.@PostConstruct
  對象初始化並賦值完成后調用
4.@PreDestroy
  對象從容器中移除之前調用
5.@BeanPostProcessor
  bean初始化前后執行的工作
6.@Value 給屬性進行賦值
  @Value("A") @Value("${從配置文件中取值}") @Vlaue("#{SpEL表達式}")
7.@ComponentScan
  @ComponentScan value:指定要掃描的包
  excludeFilters = Filter[] :指定掃描的時候按照什么規則排除那些組件
  includeFilters = Filter[] :指定掃描的時候只需要包含哪些組件【需要設置useDefaultFilters=false】
  FilterType.ANNOTATION:按照注解
  FilterType.ASSIGNABLE_TYPE:按照給定的類型;
  FilterType.ASPECTJ:使用ASPECTJ表達式
  FilterType.REGEX:使用正則指定
  FilterType.CUSTOM:使用自定義規則
8.@Bean("id值")
  給容器中注冊一個Bean;類型為返回值的類型,id默認是用方法名作為id @Bean("person")
  Bean注解的方法創建對象時的參數會從容器中獲取。
9.@Import導入組件,id默認是組件的全類名
  @Import({Color.class,Red.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
10.@Conditional({Human.class})
  類中組件統一設置。滿足當前條件,這個類中配置的所有bean注冊才能生效;

給容器中注冊組件;
  1)、包掃描+組注注解:@Component @Controller @Service @Repository
  2)、@Bean用於:導入的第三方包里面的組件
  3)、@Import[快速給容器中導入一個組件]
    1)、@Import(要導入到容器中的組件);容器中就會自動注冊這個組件,id默認是全類名
    2)、ImportSelector:返回需要導入的組件的全類名數組;
    3)、ImportBeanDefinitionRegistrar:手動注冊bean到容器中
  4)、使用Spring提供的 FactoryBean(工廠Bean);
      1)、默認獲取到的是工廠bean調用getObject創建的對象
      2)、要獲取工廠Bean本身,我們需要給id前面加一個&&colorFactoryBean
11.@Scope("prototype")
  @Lazy
  @Bean("person")
  public Person(){
    return new Person();
    }
@Scope 對象作用域
  prototype:IOC容器啟動並不會調用方法並放入容器中,而是每次需要時進行創建
  singleton:單例、IOC容器啟動后調用創建對象的方法,以后每次需要對象從容器中獲取
        ConfigurableBeanFactory#SCOPE_PROTOTYPE 多例
        ConfigurableBeanFactory#SCOPE_SINGLETON 單例
        org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request 每次同一個request調用一次
        org.springframework.web.context.WebApplicationContext#SCOPE_SESSION sesssion 每次同一個session調用一次

@Lazy :懶加載
    若為單實例,則在容器啟動后即創建對象
    若為懶加載方式,則容器啟動后不創建對象,需要時獲取Bean創建對象並初始化

12.@Profile
    Profile:Spring為我們提供的可以根據當前環境,動態的激活和切換一系列組件的功能;
    開發環境、測試環境、生產環境;
    數據源:(/A)(/B)(/C);
@Profile:指定組件在哪個環境的情況下才能被注冊到容器中,不指定,任何環境下都能注冊這個組件
    1)、加了環境標識的bean,只有這個環境被激活的時候才能注冊到容器中。默認是default環境
    2)、寫在配置類上,只有是指定的環境的時候,整個配置類里面的所有配置才能開始生效
    3)、沒有標注環境標識的bean在,任何環境下都是加載的;

啟用Profile起作用的方法有兩種方式:
  1.啟動時添加參數 -Dspring.profile.actice="指定的參數"
  2.在代碼中指定

    //1、創建一個applicationContext
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
    //2、設置需要激活的環境
    applicationContext.getEnvironment().setActiveProfiles("指定的參數");
    //3、注冊主配置類
    applicationContext.register(MyConfigOfProfile.class);
    //4、啟動刷新容器
    applicationContext.refresh();
    class MyConfigOfProfile implements EmbeddedValueResolverAware{
      @Override

      }

  

13.@PropertySource
  使用@PropertySource讀取外部配置文件中的k/v保存到運行的環境變量中;加載完外部的配置文件以后使用${}取出配置文件的值
  @PropertySource(value={"classpath:/db.properties"})

12.Bean的生命周期
  bean的生命周期:
  bean創建---初始化----銷毀的過程
  容器管理bean的生命周期;
  我們可以自定義初始化和銷毀方法;容器在bean進行到當前生命周期的時候來調用我們自定義的初始化和銷毀方法
  構造(對象創建)
  單實例:在容器啟動的時候創建對象
  多實例:在每次獲取的時候創建對象
  BeanPostProcessor.postProcessBeforeInitialization
    初始化:
    對象創建完成,並賦值好,調用初始化方法。。。
  BeanPostProcessor.postProcessAfterInitialization
    銷毀:
    單實例:容器關閉的時候
    多實例:容器不會管理這個bean;容器不會調用銷毀方法;
遍歷得到容器中所有的BeanPostProcessor;挨個執行beforeInitialization,
  一但返回null,跳出for循環,不會執行后面的BeanPostProcessor.postProcessorsBeforeInitialization
BeanPostProcessor原理
  populateBean(beanName, mbd, instanceWrapper);給bean進行屬性賦值
  initializeBean 初始化Bean
  applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  invokeInitMethods(beanName, wrappedBean, mbd);執行自定義初始化
  applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    <1> 通過@Bean(initMethod="",destoryMethod="")
    <2> 通過Bean實現InitiallizingBean與DisposableBean實現bean的初始化和銷毀
    <3> 使用JSR250定義的方式
      @PostConstruct:在bean創建完成並且屬性賦值完成后執行初始化方法
      @PreDestroy:在容器銷毀bean之前進行清理工作
    <4> 實現BeanPostProcessor接口的后置處理器方法
      postProcessBeforeInitialization:初始化之前處理
      postProcessAfterInitialization:初始化之后處理
  Spring底層對 BeanPostProcessor 的使用;
    bean賦值,注入其他組件,@Autowired,生命周期注解功能,@Async,xxx BeanPostProcessor;
13.AOP 【動態代理】 @EnableAspectJAutoProxy
  指在程序運行期間動態的將某段代碼切入到指定方法指定位置進行運行的編程方式;

    1、導入aop模塊;Spring AOP:(spring-aspects)
    2、定義一個業務邏輯類(MathCalculator);在業務邏輯運行的時候將日志進行打印(方法之前、方法運行結束、方法出現異常,xxx)
    3、定義一個日志切面類(LogAspects):切面類里面的方法需要動態感知MathCalculator.div運行到哪里然后執行;
      通知方法:
        前置通知(@Before):logStart:在目標方法(div)運行之前運行
        后置通知(@After):logEnd:在目標方法(div)運行結束之后運行(無論方法正常結束還是異常結束)
        返回通知(@AfterReturning):logReturn:在目標方法(div)正常返回之后運行
        異常通知(@AfterThrowing):logException:在目標方法(div)出現異常以后運行
        環繞通知(@Around):動態代理,手動推進目標方法運行(joinPoint.procced())
    4、給切面類的目標方法標注何時何地運行(通知注解);
    5、將切面類和業務邏輯類(目標方法所在類)都加入到容器中;
    6、必須告訴Spring哪個類是切面類(給切面類上加一個注解:@Aspect)
    7、給配置類中加 @EnableAspectJAutoProxy 【開啟基於注解的aop模式】
在Spring中很多的 @EnableXXX;
  三步:
    1)、將業務邏輯組件和切面類都加入到容器中;告訴Spring哪個是切面類(@Aspect)
    2)、在切面類上的每一個通知方法上標注通知注解,告訴Spring何時何地運行(切入點表達式)
    3)、開啟基於注解的aop模式;@EnableAspectJAutoProxy

  AOP原理:【看給容器中注冊了什么組件,這個組件什么時候工作,這個組件的功能是什么?】
  @EnableAspectJAutoProxy;
    1、@EnableAspectJAutoProxy是什么?
    @Import(AspectJAutoProxyRegistrar.class):給容器中導入AspectJAutoProxyRegistrar
    利用AspectJAutoProxyRegistrar自定義給容器中注冊bean;BeanDefinetion
    internalAutoProxyCreator=AnnotationAwareAspectJAutoProxyCreator,給容器中注冊一個AnnotationAwareAspectJAutoProxyCreator;
      2、 AnnotationAwareAspectJAutoProxyCreator:
          AnnotationAwareAspectJAutoProxyCreator
          ->AspectJAwareAdvisorAutoProxyCreator
          ->AbstractAdvisorAutoProxyCreator
          ->AbstractAutoProxyCreator
      implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
      關注后置處理器(在bean初始化完成前后做事情)、自動裝配BeanFactory
          AbstractAutoProxyCreator.setBeanFactory()
          AbstractAutoProxyCreator.有后置處理器的邏輯;
          AbstractAdvisorAutoProxyCreator.setBeanFactory()-》initBeanFactory()
          AnnotationAwareAspectJAutoProxyCreator.initBeanFactory()
        流程:
          1)、傳入配置類,創建ioc容器
          2)、注冊配置類,調用refresh()刷新容器;
          3)、registerBeanPostProcessors(beanFactory);注冊bean的后置處理器來方便攔截bean的創建;
        1)、先獲取ioc容器已經定義了的需要創建對象的所有BeanPostProcessor
        2)、給容器中加別的BeanPostProcessor
        3)、優先注冊實現了PriorityOrdered接口的BeanPostProcessor;
        4)、再給容器中注冊實現了Ordered接口的BeanPostProcessor;
        5)、注冊沒實現優先級接口的BeanPostProcessor;
        6)、注冊BeanPostProcessor,實際上就是創建BeanPostProcessor對象,保存在容器中;
    創建internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】
        1)、創建Bean的實例
        2)、populateBean;給bean的各種屬性賦值
        3)、initializeBean:初始化bean;
          1)、invokeAwareMethods():處理Aware接口的方法回調
          2)、applyBeanPostProcessorsBeforeInitialization():應用后置處理器的postProcessBeforeInitialization()
          3)、invokeInitMethods();執行自定義的初始化方法
          4)、applyBeanPostProcessorsAfterInitialization();執行后置處理器的postProcessAfterInitialization();
        4)、BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)創建成功;--》aspectJAdvisorsBuilder
          1)、把BeanPostProcessor注冊到BeanFactory中;
            beanFactory.addBeanPostProcessor(postProcessor);
        =======以上是創建和注冊AnnotationAwareAspectJAutoProxyCreator的過程========
            AnnotationAwareAspectJAutoProxyCreator => InstantiationAwareBeanPostProcessor
          4)、finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工作;創建剩下的單實例bean
            1)、遍歷獲取容器中所有的Bean,依次創建對象getBean(beanName);
                getBean->doGetBean()->getSingleton()->
            2)、創建bean
      【AnnotationAwareAspectJAutoProxyCreator在所有bean創建之前會有一個攔截,InstantiationAwareBeanPostProcessor,會調用postProcessBeforeInstantiation()】
          1)、先從緩存中獲取當前bean,如果能獲取到,說明bean是之前被創建過的,直接使用,否則再創建;只要創建好的Bean都會被緩存起來
          2)、createBean();創建bean;
              AnnotationAwareAspectJAutoProxyCreator 會在任何bean創建之前先嘗試返回bean的實例
              【BeanPostProcessor是在Bean對象創建完成初始化前后調用的】
              【InstantiationAwareBeanPostProcessor是在創建Bean實例之前先嘗試用后置處理器返回對象的】
          1)、resolveBeforeInstantiation(beanName, mbdToUse);解析BeforeInstantiation
              希望后置處理器在此能返回一個代理對象;如果能返回代理對象就使用,如果不能就繼續
            1)、后置處理器先嘗試返回對象;
                bean = applyBeanPostProcessorsBeforeInstantiation():
                拿到所有后置處理器,如果是InstantiationAwareBeanPostProcessor;
                就執行postProcessBeforeInstantiation
                  if (bean != null) {
                      bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                  }
            2)、doCreateBean(beanName, mbdToUse, args);真正的去創建一個bean實例;和3.6流程一樣;


AnnotationAwareAspectJAutoProxyCreator【InstantiationAwareBeanPostProcessor】 的作用:
  1)、每一個bean創建之前,調用postProcessBeforeInstantiation();
    關心MathCalculator和LogAspect的創建
    1)、判斷當前bean是否在advisedBeans中(保存了所有需要增強bean)
    2)、判斷當前bean是否是基礎類型的Advice、Pointcut、Advisor、AopInfrastructureBean,或者是否是切面(@Aspect)
    3)、是否需要跳過
  1)、獲取候選的增強器(切面里面的通知方法)【List<Advisor> candidateAdvisors】
    每一個封裝的通知方法的增強器是 InstantiationModelAwarePointcutAdvisor;
    判斷每一個增強器是否是 AspectJPointcutAdvisor 類型的;返回true
  2)、永遠返回false
2)、創建對象
  postProcessAfterInitialization;
    return wrapIfNecessary(bean, beanName, cacheKey);//包裝如果需要的情況下
    1)、獲取當前bean的所有增強器(通知方法) Object[] specificInterceptors
      1、找到候選的所有的增強器(找哪些通知方法是需要切入當前bean方法的)
      2、獲取到能在bean使用的增強器。
      3、給增強器排序
    2)、保存當前bean在advisedBeans中;
    3)、如果當前bean需要增強,創建當前bean的代理對象;
      1)、獲取所有增強器(通知方法)
      2)、保存到proxyFactory
      3)、創建代理對象:Spring自動決定
    JdkDynamicAopProxy(config);jdk動態代理;
    ObjenesisCglibAopProxy(config);cglib的動態代理;
      4)、給容器中返回當前組件使用cglib增強了的代理對象;
      5)、以后容器中獲取到的就是這個組件的代理對象,執行目標方法的時候,代理對象就會執行通知方法的流程;


3)、目標方法執行;
    容器中保存了組件的代理對象(cglib增強后的對象),這個對象里面保存了詳細信息(比如增強器,目標對象,xxx);
    1)、CglibAopProxy.intercept();攔截目標方法的執行
    2)、根據ProxyFactory對象獲取將要執行的目標方法攔截器鏈;
      List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
        1)、List<Object> interceptorList保存所有攔截器 5
          一個默認的ExposeInvocationInterceptor 和 4個增強器;
        2)、遍歷所有的增強器,將其轉為Interceptor;
          registry.getInterceptors(advisor);
        3)、將增強器轉為List<MethodInterceptor>;
          如果是MethodInterceptor,直接加入到集合中
          如果不是,使用AdvisorAdapter將增強器轉為MethodInterceptor;
          轉換完成返回MethodInterceptor數組;
    3)、如果沒有攔截器鏈,直接執行目標方法;
          攔截器鏈(每一個通知方法又被包裝為方法攔截器,利用MethodInterceptor機制)
    4)、如果有攔截器鏈,把需要執行的目標對象,目標方法,
          攔截器鏈等信息傳入創建一個 CglibMethodInvocation 對象,
          並調用 Object retVal = mi.proceed();
    5)、攔截器鏈的觸發過程;
          1)、如果沒有攔截器執行執行目標方法,或者攔截器的索引和攔截器數組-1大小一樣(指定到了最后一個攔截器)執行目標方法;
          2)、鏈式獲取每一個攔截器,攔截器執行invoke方法,每一個攔截器等待下一個攔截器執行完成返回以后再來執行;
攔截器鏈的機制,保證通知方法與目標方法的執行順序;

總結:
  1)、 @EnableAspectJAutoProxy 開啟AOP功能
  2)、 @EnableAspectJAutoProxy 會給容器中注冊一個組件 AnnotationAwareAspectJAutoProxyCreator
  3)、AnnotationAwareAspectJAutoProxyCreator是一個后置處理器;
  4)、容器的創建流程:
    1)、registerBeanPostProcessors()注冊后置處理器;創建AnnotationAwareAspectJAutoProxyCreator對象
    2)、finishBeanFactoryInitialization()初始化剩下的單實例bean
      1)、創建業務邏輯組件和切面組件
      2)、AnnotationAwareAspectJAutoProxyCreator攔截組件的創建過程
      3)、組件創建完之后,判斷組件是否需要增強
          是:切面的通知方法,包裝成增強器(Advisor);給業務邏輯組件創建一個代理對象(cglib);
    5)、執行目標方法:
      1)、代理對象執行目標方法
      2)、CglibAopProxy.intercept();
        1)、得到目標方法的攔截器鏈(增強器包裝成攔截器MethodInterceptor)
        2)、利用攔截器的鏈式機制,依次進入每一個攔截器進行執行;
      3)、效果:
          正常執行:前置通知-》目標方法-》后置通知-》返回通知
          出現異常:前置通知-》目標方法-》后置通知-》異常通知

16.擴展原理:
  BeanPostProcessor:bean后置處理器,bean創建對象初始化前后進行攔截工作的
    1、BeanFactoryPostProcessor:beanFactory的后置處理器;
    在BeanFactory標准初始化之后調用,來定制和修改BeanFactory的內容;
    所有的bean定義已經保存加載到beanFactory,但是bean的實例還未創建
    BeanFactoryPostProcessor原理:
      1)、ioc容器創建對象
      2)、invokeBeanFactoryPostProcessors(beanFactory);
        如何找到所有的BeanFactoryPostProcessor並執行他們的方法;
        1)、直接在BeanFactory中找到所有類型是BeanFactoryPostProcessor的組件,並執行他們的方法
        2)、在初始化創建其他組件前面執行
2、BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor
    postProcessBeanDefinitionRegistry();
    在所有bean定義信息將要被加載,bean實例還未創建的;
    優先於BeanFactoryPostProcessor執行;
    利用BeanDefinitionRegistryPostProcessor給容器中再額外添加一些組件;
原理:
  1)、ioc創建對象
  2)、refresh()-》invokeBeanFactoryPostProcessors(beanFactory);
  3)、從容器中獲取到所有的BeanDefinitionRegistryPostProcessor組件。
    1、依次觸發所有的postProcessBeanDefinitionRegistry()方法
    2、再來觸發postProcessBeanFactory()方法BeanFactoryPostProcessor;
  4)、再來從容器中找到BeanFactoryPostProcessor組件;然后依次觸發postProcessBeanFactory()方法

3、ApplicationListener:監聽容器中發布的事件。事件驅動模型開發;
  public interface ApplicationListener<E extends ApplicationEvent>
    監聽 ApplicationEvent 及其下面的子事件;
    步驟:
      1)、寫一個監聽器(ApplicationListener實現類)來監聽某個事件(ApplicationEvent及其子類)
        @EventListener;
        原理:使用EventListenerMethodProcessor處理器來解析方法上的@EventListener;
      2)、把監聽器加入到容器;
      3)、只要容器中有相關事件的發布,我們就能監聽到這個事件;
        ContextRefreshedEvent:容器刷新完成(所有bean都完全創建)會發布這個事件;
        ContextClosedEvent:關閉容器會發布這個事件;
      4)、發布一個事件:
         applicationContext.publishEvent();

          原理:
            ContextRefreshedEvent、IOCTest_Ext$1[source=我發布的時間]、ContextClosedEvent;
            1)、ContextRefreshedEvent事件:
              1)、容器創建對象:refresh();
              2)、finishRefresh();容器刷新完成會發布ContextRefreshedEvent事件
              3)、自己發布事件;
              4)、容器關閉會發布ContextClosedEvent;

      【事件發布流程】:
         publishEvent(new ContextRefreshedEvent(this));
          1)、獲取事件的多播器(派發器):getApplicationEventMulticaster()
          2)、multicastEvent派發事件:
          3)、獲取到所有的ApplicationListener;
            for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
              1)、如果有Executor,可以支持使用Executor進行異步派發;
                Executor executor = getTaskExecutor();
              2)、否則,同步的方式直接執行listener方法;invokeListener(listener, event);
                  拿到listener回調onApplicationEvent方法;

    【事件多播器(派發器)】
      1)、容器創建對象:refresh();
      2)、initApplicationEventMulticaster();初始化ApplicationEventMulticaster;
        1)、先去容器中找有沒有id=“applicationEventMulticaster”的組件;
        2)、如果沒有this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
          並且加入到容器中,我們就可以在其他組件要派發事件,自動注入這個applicationEventMulticaster;

    【容器中有哪些監聽器】
    1)、容器創建對象:refresh();
    2)、registerListeners();
    從容器中拿到所有的監聽器,把他們注冊到applicationEventMulticaster中;
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
      //將listener注冊到ApplicationEventMulticaster中
      getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);

  SmartInitializingSingleton 原理:->afterSingletonsInstantiated();
    1)、ioc容器創建對象並refresh();
    2)、finishBeanFactoryInitialization(beanFactory);初始化剩下的單實例bean;
      1)、先創建所有的單實例bean;getBean();
      2)、獲取所有創建好的單實例bean,判斷是否是SmartInitializingSingleton類型的;
        如果是就調用afterSingletonsInstantiated();

  17.聲明式事務 @EnableTransactional
    環境搭建:
    1、導入相關依賴
      據源、數據庫驅動、Spring-jdbc模塊
    2、配置數據源、JdbcTemplate(Spring提供的簡化數據庫操作的工具)操作數據
    3、給方法上標注 @Transactional 表示當前方法是一個事務方法;
    4、 @EnableTransactionManagement 開啟基於注解的事務管理功能;
      @EnableXXX
    5、配置事務管理器來控制事務;
        @Bean
        public PlatformTransactionManager transactionManager()
    原理:
      1)、@EnableTransactionManagement
        利用TransactionManagementConfigurationSelector給容器中會導入組件
        導入兩個組件
        AutoProxyRegistrar
        ProxyTransactionManagementConfiguration
    2)、AutoProxyRegistrar:
      給容器中注冊一個 InfrastructureAdvisorAutoProxyCreator 組件;
        InfrastructureAdvisorAutoProxyCreator:?
        利用后置處理器機制在對象創建以后,包裝對象,返回一個代理對象(增強器),代理對象執行方法利用攔截器鏈進行調用;
    3)、ProxyTransactionManagementConfiguration 做了什么?
      1、給容器中注冊事務增強器;
        1)、事務增強器要用事務注解的信息,AnnotationTransactionAttributeSource解析事務注解
        2)、事務攔截器:
      TransactionInterceptor;保存了事務屬性信息,事務管理器;他是一個 MethodInterceptor;在目標方法執行的時候執行攔截器鏈;
      事務攔截器:
        1)、先獲取事務相關的屬性
        2)、再獲取PlatformTransactionManager,如果事先沒有添加指定任何transactionmanger
           最終會從容器中按照類型獲取一個PlatformTransactionManager;
        3)、執行目標方法
          如果異常,獲取到事務管理器,利用事務管理回滾操作;
          如果正常,利用事務管理器,提交事務

18.spring容器初始化加載過程
1.通過配置類文件加載

public AnnotationConfigApplicationContext(Class... annotatedClasses) {
    this();
    this.register(annotatedClasses);
    this.refresh();
}

  


2.通過xml配置文件加載

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
    super(parent);
    this.setConfigLocations(configLocations);
    if (refresh) {
        this.refresh();
    }
}    

  


3.refresh():最終執行過程分析

public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);

try {
    this.postProcessBeanFactory(beanFactory);
    this.invokeBeanFactoryPostProcessors(beanFactory);
    this.registerBeanPostProcessors(beanFactory);
    this.initMessageSource();
    this.initApplicationEventMulticaster();
    this.onRefresh();
    this.registerListeners();
    this.finishBeanFactoryInitialization(beanFactory);
    this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}

this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}

}
}

  


Spring容器的refresh()【創建刷新】;
  1、prepareRefresh()刷新前的預處理;
    1)、initPropertySources()初始化一些屬性設置;子類自定義個性化的屬性設置方法;
    2)、getEnvironment().validateRequiredProperties();檢驗屬性的合法等
    3)、earlyApplicationEvents= new LinkedHashSet<ApplicationEvent>();保存容器中的一些早期的事件;
  2、obtainFreshBeanFactory();獲取BeanFactory;
    1)、refreshBeanFactory();刷新【創建】BeanFactory;
      創建了一個this.beanFactory = new DefaultListableBeanFactory();
      設置id;
    2)、getBeanFactory();返回剛才GenericApplicationContext創建的BeanFactory對象;
    3)、將創建的BeanFactory【DefaultListableBeanFactory】返回;
  3、prepareBeanFactory(beanFactory);BeanFactory的預准備工作(BeanFactory進行一些設置);
    1)、設置BeanFactory的類加載器、支持表達式解析器...
    2)、添加部分BeanPostProcessor【ApplicationContextAwareProcessor】
    3)、設置忽略的自動裝配的接口EnvironmentAware、EmbeddedValueResolverAware、xxx;
    4)、注冊可以解析的自動裝配;我們能直接在任何組件中自動注入:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
    5)、添加BeanPostProcessor【ApplicationListenerDetector】
    6)、添加編譯時的AspectJ;
    7)、給BeanFactory中注冊一些能用的組件;
      environment【ConfigurableEnvironment】、
      systemProperties【Map<String, Object>】、
      systemEnvironment【Map<String, Object>】
  4、postProcessBeanFactory(beanFactory);BeanFactory准備工作完成后進行的后置處理工作;
    1)、子類通過重寫這個方法來在BeanFactory創建並預准備完成以后做進一步的設置
======================以上是BeanFactory的創建及預准備工作==================================
  5、invokeBeanFactoryPostProcessors(beanFactory);執行BeanFactoryPostProcessor的方法;
    BeanFactoryPostProcessor:BeanFactory的后置處理器。在BeanFactory標准初始化之后執行的;
        兩個接口:BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
      1)、執行BeanFactoryPostProcessor的方法;
          先執行BeanDefinitionRegistryPostProcessor
          1)、獲取所有的BeanDefinitionRegistryPostProcessor;
          2)、看先執行實現了PriorityOrdered優先級接口的BeanDefinitionRegistryPostProcessor、
              postProcessor.postProcessBeanDefinitionRegistry(registry)
          3)、在執行實現了Ordered順序接口的BeanDefinitionRegistryPostProcessor;
            postProcessor.postProcessBeanDefinitionRegistry(registry)
          4)、最后執行沒有實現任何優先級或者是順序接口的BeanDefinitionRegistryPostProcessors;
            postProcessor.postProcessBeanDefinitionRegistry(registry)

      再執行BeanFactoryPostProcessor的方法
        1)、獲取所有的BeanFactoryPostProcessor
        2)、看先執行實現了PriorityOrdered優先級接口的BeanFactoryPostProcessor、
          postProcessor.postProcessBeanFactory()
        3)、在執行實現了Ordered順序接口的BeanFactoryPostProcessor;
          postProcessor.postProcessBeanFactory()
        4)、最后執行沒有實現任何優先級或者是順序接口的BeanFactoryPostProcessor;
          postProcessor.postProcessBeanFactory()
  6、registerBeanPostProcessors(beanFactory);注冊BeanPostProcessor(Bean的后置處理器)【 intercept bean creation】
      不同接口類型的BeanPostProcessor;在Bean創建前后的執行時機是不一樣的
      BeanPostProcessor、
      DestructionAwareBeanPostProcessor、
      InstantiationAwareBeanPostProcessor、
      SmartInstantiationAwareBeanPostProcessor、
      MergedBeanDefinitionPostProcessor【internalPostProcessors】、

      1)、獲取所有的 BeanPostProcessor;后置處理器都默認可以通過PriorityOrdered、Ordered接口來執行優先級
      2)、先注冊PriorityOrdered優先級接口的BeanPostProcessor;把每一個BeanPostProcessor;添加到BeanFactory中
beanFactory.addBeanPostProcessor(postProcessor);
      3)、再注冊Ordered接口的
      4)、最后注冊沒有實現任何優先級接口的
      5)、最終注冊MergedBeanDefinitionPostProcessor;
      6)、注冊一個ApplicationListenerDetector;來在Bean創建完成后檢查是否是ApplicationListener,如果是
              applicationContext.addApplicationListener((ApplicationListener<?>) bean);
  7、initMessageSource();初始化MessageSource組件(做國際化功能;消息綁定,消息解析);
      1)、獲取BeanFactory
      2)、看容器中是否有id為messageSource的,類型是MessageSource的組件
          如果有賦值給messageSource,如果沒有自己創建一個DelegatingMessageSource;
          MessageSource:取出國際化配置文件中的某個key的值;能按照區域信息獲取;
      3)、把創建好的MessageSource注冊在容器中,以后獲取國際化配置文件的值的時候,可以自動注入MessageSource;
          beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
          MessageSource.getMessage(String code, Object[] args, String defaultMessage, Locale locale);
  8、initApplicationEventMulticaster();初始化事件派發器;
      1)、獲取BeanFactory
      2)、從BeanFactory中獲取applicationEventMulticaster的ApplicationEventMulticaster;
      3)、如果上一步沒有配置;創建一個SimpleApplicationEventMulticaster
      4)、將創建的ApplicationEventMulticaster添加到BeanFactory中,以后其他組件直接自動注入
  9、onRefresh();留給子容器(子類)
    1、子類重寫這個方法,在容器刷新的時候可以自定義邏輯;
  10、registerListeners();給容器中將所有項目里面的ApplicationListener注冊進來;
    1、從容器中拿到所有的ApplicationListener
    2、將每個監聽器添加到事件派發器中;
    getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    3、派發之前步驟產生的事件;
  11、finishBeanFactoryInitialization(beanFactory);初始化所有剩下的單實例bean;
    1、beanFactory.preInstantiateSingletons();初始化后剩下的單實例bean
      1)、獲取容器中的所有Bean,依次進行初始化和創建對象
      2)、獲取Bean的定義信息;RootBeanDefinition
      3)、Bean不是抽象的,是單實例的,是懶加載;
        1)、判斷是否是FactoryBean;是否是實現FactoryBean接口的Bean;
        2)、不是工廠Bean。利用getBean(beanName);創建對象
          0、getBean(beanName); ioc.getBean();
          1、doGetBean(name, null, null, false);
          2、先獲取緩存中保存的單實例Bean。如果能獲取到說明這個Bean之前被創建過(所有創建過的單實例Bean都會被緩存起來)
            從private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);獲取的
          3、緩存中獲取不到,開始Bean的創建對象流程;
          4、標記當前bean已經被創建
          5、獲取Bean的定義信息;
          6、【獲取當前Bean依賴的其他Bean;如果有按照getBean()把依賴的Bean先創建出來;】
          7、啟動單實例Bean的創建流程;
            1)、createBean(beanName, mbd, args);
            2)、Object bean = resolveBeforeInstantiation(beanName, mbdToUse);讓BeanPostProcessor先攔截返回代理對象;
    【InstantiationAwareBeanPostProcessor】:提前執行;
        先觸發:postProcessBeforeInstantiation();
        如果有返回值:觸發postProcessAfterInitialization();
    3)、如果前面的InstantiationAwareBeanPostProcessor沒有返回代理對象;調用4)
    4)、Object beanInstance = doCreateBean(beanName, mbdToUse, args);創建Bean
      1)、【創建Bean實例】;createBeanInstance(beanName, mbd, args);
        利用工廠方法或者對象的構造器創建出Bean實例;
      2)、applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
        調用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition(mbd, beanType, beanName);
      3)、【Bean屬性賦值】populateBean(beanName, mbd, instanceWrapper);
        賦值之前:
        1)、拿到InstantiationAwareBeanPostProcessor后置處理器;
          postProcessAfterInstantiation();
        2)、拿到InstantiationAwareBeanPostProcessor后置處理器;
          postProcessPropertyValues();
            =====賦值之前:===
        3)、應用Bean屬性的值;為屬性利用setter方法等進行賦值;
            applyPropertyValues(beanName, mbd, bw, pvs);
        4)、【Bean初始化】initializeBean(beanName, exposedObject, mbd);
          1)、【執行Aware接口方法】invokeAwareMethods(beanName, bean);執行xxxAware接口的方法
            BeanNameAware\BeanClassLoaderAware\BeanFactoryAware
          2)、【執行后置處理器初始化之前】applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
            BeanPostProcessor.postProcessBeforeInitialization();
          3)、【執行初始化方法】invokeInitMethods(beanName, wrappedBean, mbd);
            1)、是否是InitializingBean接口的實現;執行接口規定的初始化;
            2)、是否自定義初始化方法;
          4)、【執行后置處理器初始化之后】applyBeanPostProcessorsAfterInitialization
            BeanPostProcessor.postProcessAfterInitialization();
          5)、注冊Bean的銷毀方法;
            將創建的Bean添加到緩存中singletonObjects;
          ioc容器就是這些Map;很多的Map里面保存了單實例Bean,環境信息。。。。;
          所有Bean都利用getBean創建完成以后;
          檢查所有的Bean是否是SmartInitializingSingleton接口的;如果是;就執行afterSingletonsInstantiated();


12、finishRefresh();完成BeanFactory的初始化創建工作;IOC容器就創建完成;
  1)、initLifecycleProcessor();初始化和生命周期有關的后置處理器;LifecycleProcessor
      默認從容器中找是否有lifecycleProcessor的組件【LifecycleProcessor】;如果沒有new DefaultLifecycleProcessor();加入到容器;

      寫一個LifecycleProcessor的實現類,可以在BeanFactory
      void onRefresh();
      void onClose();
  2)、 getLifecycleProcessor().onRefresh();
      拿到前面定義的生命周期處理器(BeanFactory);回調onRefresh();
  3)、publishEvent(new ContextRefreshedEvent(this));發布容器刷新完成事件;
  4)、liveBeansView.registerApplicationContext(this);

======總結===========

  • Spring容器在啟動的時候,先會保存所有注冊進來的Bean的定義信息;
  • xml注冊bean;<bean>
  • 注解注冊Bean;@Service、@Component、@Bean、xxx
  • Spring容器會合適的時機創建這些Bean
  • 用到這個bean的時候;利用getBean創建bean;創建好以后保存在容器中;
  • 統一創建剩下所有的bean的時候;finishBeanFactoryInitialization();
  • 后置處理器;BeanPostProcessor
  • 每一個bean創建完成,都會使用各種后置處理器進行處理;來增強bean的功能;
  • AutowiredAnnotationBeanPostProcessor:處理自動注入
  • AnnotationAwareAspectJAutoProxyCreator:來做AOP功能;xxx....增強的功能注解:
  • AsyncAnnotationBeanPostProcessor

....
4)、事件驅動模型;
ApplicationListener;事件監聽;
ApplicationEventMulticaster;事件派發:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM