Spring使用_進階

概述

  本文主要寫了幾個關於Spring Aware,多線程,計劃任務(定時任務),條件註解,組合註解,元註解,Spring測試的小例子以及關於@Enable*註解的工做原理的理解。java


 

Spring Aware

  簡介:linux

    Spring的依賴注入的最大亮點就是你全部的Bean對Spring容器的存在是沒有意識的。即你能夠將你的容器替換成別的容器,如Google Guice,這是Bean之間的耦合度很低。spring

    可是在實際項目中,有時會不可避免的要用到Spring容器自己的功能資源,這是你的Bean必需要意識到Spring容器的存在,才能調用Spring所提供的資源,這就是Spring Aware。數據庫

    其實Spring Aware原本就是Spring設計用來框架內部使用的,若使用了Spring Aware,你的Bean將會和Spring框架耦合。apache

  例子:編程

 1 package com.wisely.highlight_spring4.ch3.aware;
 2 
 3 import org.apache.commons.io.IOUtils;
 4 import org.springframework.beans.factory.BeanNameAware;
 5 import org.springframework.context.ResourceLoaderAware;
 6 import org.springframework.core.io.Resource;
 7 import org.springframework.core.io.ResourceLoader;
 8 import org.springframework.stereotype.Service;
 9 
10 import java.io.IOException;
11 
12 /**
13  * Spring Aware演示Bean
14  * 實現BeanNameAware、ResourceLoaderAware接口,得到Bean名稱和資源加載的服務。
15  */
16 @Service
17 public class AwareService implements BeanNameAware, ResourceLoaderAware {//1
18 
19     private String beanName;
20     private ResourceLoader loader;
21     //實現ResourceLoaderAware需重寫setResourceLoader方法
22     @Override
23     public void setResourceLoader(ResourceLoader resourceLoader) {//2
24         this.loader = resourceLoader;
25     }
26     //實現BeanNameAware需重寫setBeanName方法
27     @Override
28     public void setBeanName(String name) {//3
29         this.beanName = name;
30     }
31 
32     public void outputResult() {
33         System.out.println("Bean的名稱爲:" + beanName);
34         Resource resource = loader.getResource("classpath:com/wisely/highlight_spring4/ch3/aware/test.txt");
35         try {
36             System.out.println("ResourceLoader加載的文件內容爲: " + IOUtils.toString(resource.getInputStream()));
37         } catch (IOException e) {
38             e.printStackTrace();
39         }
40     }
41 }
Spring Aware演示Bean
 1 package com.wisely.highlight_spring4.ch3.aware;
 2 
 3 import org.springframework.context.annotation.ComponentScan;
 4 import org.springframework.context.annotation.Configuration;
 5 
 6 /**
 7  * 配置類
 8  */
 9 @Configuration
10 @ComponentScan("com.wisely.highlight_spring4.ch3.aware")
11 public class AwareConfig {
12 
13 }
配置類
 1 package com.wisely.highlight_spring4.ch3.aware;
 2 
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 /**
 6  * 運行
 7  */
 8 public class Main {
 9     public static void main(String[] args) {
10         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AwareConfig.class);
11         AwareService awareService = context.getBean(AwareService.class);
12         awareService.outputResult();
13         context.close();
14     }
15 }
運行

多線程

  簡介:windows

    Spring經過任務執行器(TaskExecutor)來實現多線程和併發編程,使用ThreadPoolTaskExecutor可實現一個基於線程池的TaskExecutor。網絡

    而實際開發中任務通常是非阻礙的(異步的),因此咱們要在配置類中經過@EnableAsync開啓對異步任務的支持,並經過在實際執行的Bean的方法中使用@Async註解來聲明其是一個異步任務。多線程

  例子:併發

 1 package com.wisely.highlight_spring4.ch3.taskexecutor;
 2 
 3 import org.springframework.scheduling.annotation.Async;
 4 import org.springframework.stereotype.Service;
 5 
 6 /**
 7  * 任務執行類
 8  */
 9 @Service
10 public class AsyncTaskService {
11     /**
12      * 經過@Async註解代表該方法是一個異步方法,若是註解在類級別,則代表該類全部的方法都是異步方法。
13      * 而這裏的方法自動被注入使用ThreadPoolTaskExecutor做爲TaskExecutor。
14      * @param i
15      */
16     @Async
17     public void executeAsyncTask(Integer i){
18         System.out.println("執行異步任務: "+i);
19     }
20 
21     @Async
22     public void executeAsyncTaskPlus(Integer i){
23         System.out.println("執行異步任務+1: "+(i+1));
24     }
25 
26 }
任務執行類
 1 package com.wisely.highlight_spring4.ch3.taskexecutor;
 2 
 3 import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
 4 import org.springframework.context.annotation.ComponentScan;
 5 import org.springframework.context.annotation.Configuration;
 6 import org.springframework.scheduling.annotation.AsyncConfigurer;
 7 import org.springframework.scheduling.annotation.EnableAsync;
 8 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 9 
10 import java.util.concurrent.Executor;
11 
12 /**
13  * 配置類
14  */
15 @Configuration
16 @ComponentScan("com.wisely.highlight_spring4.ch3.taskexecutor")
17 @EnableAsync //使用@EnableAsync註解開啓異步任務支持
18 public class TaskExecutorConfig implements AsyncConfigurer {//實現AsyncConfigurer接口
19 
20     /**
21      * 重寫AsyncConfigurer接口的getAsyncExecutor方法,並返回一個ThreadPoolTaskExecutor
22      * 這樣就能夠得到一個基於線程池的TaskExecutor
23      * @return
24      */
25     @Override
26     public Executor getAsyncExecutor() {
27         ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
28         //設置核心池大小
29         taskExecutor.setCorePoolSize(5);
30         //設置最大池大小
31         taskExecutor.setMaxPoolSize(10);
32         //設置隊列容量
33         taskExecutor.setQueueCapacity(25);
34         //初始化
35         taskExecutor.initialize();
36         return taskExecutor;
37     }
38 
39     @Override
40     public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
41         return null;
42     }
43 }
配置類
 1 package com.wisely.highlight_spring4.ch3.taskexecutor;
 2 
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 /**
 6  * 運行
 7  */
 8 public class Main {
 9     public static void main(String[] args) {
10         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TaskExecutorConfig.class);
11         AsyncTaskService asyncTaskService = context.getBean(AsyncTaskService.class);
12         for (int i = 0; i < 10; i++) {
13             asyncTaskService.executeAsyncTask(i);
14             asyncTaskService.executeAsyncTaskPlus(i);
15         }
16         context.close();
17     }
18 }
運行

 

計劃任務(定時任務)

  簡介:

    從Spring3.1開始,計劃任務在Spring中的實現變得異常的簡單。首先經過在配置類註解@EnableScheduling來開啓對計劃任務的支持,而後在要執行計劃任務的方法上註解@Scheduled,聲明這是一個計劃任務。

    Spring經過@Scheduled支持多種類型的計劃任務,包含cron、fixDelay、fixRate等。

  例子:

 1 package com.wisely.highlight_spring4.ch3.taskscheduler;
 2 
 3 import org.springframework.scheduling.annotation.Scheduled;
 4 import org.springframework.stereotype.Service;
 5 
 6 import java.text.SimpleDateFormat;
 7 import java.util.Date;
 8 
 9 /**
10  * 計劃任務執行類
11  */
12 @Service
13 public class ScheduledTaskService {
14 
15     private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
16 
17     /**
18      * 經過@Scheduled註解聲明該方法是計劃任務,使用fixedRate屬性每隔固定時間執行。
19      */
20     @Scheduled(fixedRate = 5000)
21     public void reportCurrentTime() {
22         System.out.println("每隔五秒執行一次 " + dateFormat.format(new Date()));
23     }
24 
25     /**
26      * 1:使用cron屬性可按照指定時間執行,這裏是天天11點28分執行
27      * 2:cron是UNIX和類UNIX(Linux)系統下的定時任務
28      */
29     @Scheduled(cron = "0 28 11 ? * *")
30     public void fixTimeExecution() {
31         System.out.println("在指定時間 " + dateFormat.format(new Date()) + "執行");
32     }
33 }
計劃任務執行類
 1 package com.wisely.highlight_spring4.ch3.taskscheduler;
 2 
 3 import org.springframework.context.annotation.ComponentScan;
 4 import org.springframework.context.annotation.Configuration;
 5 import org.springframework.scheduling.annotation.EnableScheduling;
 6 
 7 /**
 8  * 配置類
 9  */
10 @Configuration
11 @ComponentScan("com.wisely.highlight_spring4.ch3.taskscheduler")
12 @EnableScheduling //經過@EnableScheduling註解開啓對計劃任務的支持。
13 public class TaskSchedulerConfig {
14 
15 }
配置類
 1 package com.wisely.highlight_spring4.ch3.taskscheduler;
 2 
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 /**
 6  * 運行
 7  */
 8 public class Main {
 9     public static void main(String[] args) {
10          AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TaskSchedulerConfig.class);
11     }
12 }
運行

條件註解(@Conditional)

  簡介:

    一句話來講:@Conditional註解能夠根據特定條件建立特定的Bean。

  例子:

 1 package com.wisely.highlight_spring4.ch3.conditional;
 2 
 3 import org.springframework.context.annotation.Condition;
 4 import org.springframework.context.annotation.ConditionContext;
 5 import org.springframework.core.type.AnnotatedTypeMetadata;
 6 
 7 /**
 8  * 判斷條件定義
 9  * 判斷Linux的條件
10  */
11 public class LinuxCondition implements Condition {//實現Condition接口
12 
13     /**
14      * 重寫Condition接口的matches方法來構造判斷條件
15      * @param context
16      * @param metadata
17      * @return
18      */
19     public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
20         return context.getEnvironment().getProperty("os.name").contains("Linux");
21     }
22 }
判斷條件定義_Linux
 1 package com.wisely.highlight_spring4.ch3.conditional;
 2 
 3 import org.springframework.context.annotation.Condition;
 4 import org.springframework.context.annotation.ConditionContext;
 5 import org.springframework.core.type.AnnotatedTypeMetadata;
 6 
 7 /**
 8  * 判斷條件定義
 9  * 判斷Windows的條件
10  */
11 public class WindowsCondition implements Condition {//實現Condition接口
12 
13     /**
14      * 重寫Condition接口的matches方法來構造判斷條件
15      * @param context
16      * @param metadata
17      * @return
18      */
19     public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
20         return context.getEnvironment().getProperty("os.name").contains("Windows");
21     }
22 }
判斷條件定義_Windows
1 package com.wisely.highlight_spring4.ch3.conditional;
2 
3 /**
4  * 不一樣系統下Bean的類
5  * 接口
6  */
7 public interface ListService {
8     public String showListCmd();
9 }
不一樣系統下Bean的類_接口
 1 package com.wisely.highlight_spring4.ch3.conditional;
 2 
 3 /**
 4  * 不一樣系統下Bean的類
 5  * Linux下所要建立的Bean的類
 6  */
 7 public class LinuxListService implements ListService{
 8 
 9     @Override
10     public String showListCmd() {
11         return "ls";
12     }
13 }
不一樣系統下Bean的類_Linux
 1 package com.wisely.highlight_spring4.ch3.conditional;
 2 
 3 /**
 4  * 不一樣系統下Bean的類
 5  * Windows下所要建立的Bean的類
 6  */
 7 public class WindowsListService implements ListService {
 8 
 9     @Override
10     public String showListCmd() {
11         return "dir";
12     }
13 }
不一樣系統下Bean的類_Windows
 1 package com.wisely.highlight_spring4.ch3.conditional;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Conditional;
 5 import org.springframework.context.annotation.Configuration;
 6 
 7 /**
 8  * 配置類
 9  */
10 @Configuration
11 public class ConditionConfig {
12 
13     /**
14      * 經過@Conditional註解,符合Windows條件則實例化windowsListService
15      * @return
16      */
17     @Bean
18     @Conditional(WindowsCondition.class)
19     public ListService windowsListService() {
20         return new WindowsListService();
21     }
22 
23     /**
24      * 經過@Conditional註解,符合Linux條件則實例化linuxListService
25      * @return
26      */
27     @Bean
28     @Conditional(LinuxCondition.class)
29     public ListService linuxListService() {
30         return new LinuxListService();
31     }
32 }
配置類
 1 package com.wisely.highlight_spring4.ch3.conditional;
 2 
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 /**
 6  * 運行
 7  */
 8 public class Main {
 9 
10     public static void main(String[] args) {
11         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConditionConfig.class);
12         ListService listService = context.getBean(ListService.class);
13         System.out.println(context.getEnvironment().getProperty("os.name") + "系統下的列表命令爲: " + listService.showListCmd());
14         context.close();
15     }
16 }
運行

 

組合註解與元註解

  簡介:

    從Spring2開始,爲了響應JDK1.5推出的註解功能,Spring開始大量加入註解來替代xml配置。Spring的註解主要用來配置和注入Bean,以及AOP相關配置。

    隨着註解的大量使用,尤爲相同的多個註解用到各個類或者方法中,會至關繁瑣。這就造成了所謂的樣板代碼(boilerplate code),是Spring涉及原則中要消除的代碼。

    所謂的元註解其實就是能夠註解到別的註解上的註解,被註解的註解稱之爲組合註解,組合主借具有註解在上面的元註解的功能。Spring的不少註解均可以做爲元註解,並且Spring自己已經有不少組合註解。如@Configuration就是一個組合@Component註解,代表這個類其實也是一個Bean。

  例子:

 1 package com.wisely.highlight_spring4.ch3.annotation;
 2 
 3 import org.springframework.context.annotation.ComponentScan;
 4 import org.springframework.context.annotation.Configuration;
 5 
 6 import java.lang.annotation.*;
 7 
 8 /**
 9  * 組合註解
10  */
11 @Target(ElementType.TYPE)
12 @Retention(RetentionPolicy.RUNTIME)
13 @Documented
14 @Configuration //組合@Configuration元註解
15 @ComponentScan //組合@ComponentScan註解
16 public @interface WiselyConfiguration {
17     
18     String[] value() default {}; //覆蓋value參數
19 
20 }
組合註解
 1 package com.wisely.highlight_spring4.ch3.annotation;
 2 
 3 import org.springframework.stereotype.Service;
 4 
 5 /**
 6  * 服務Bean
 7  */
 8 @Service
 9 public class DemoService {
10     
11     public void outputResult(){
12         System.out.println("從組合註解配置照樣得到的bean");
13     }
14 }
服務Bean
 1 package com.wisely.highlight_spring4.ch3.annotation;
 2 
 3 /**
 4  * 配置類
 5  * 使用@WiselyConfiguration註解替代@Configuration和@ComponentScan註解。
 6  */
 7 @WiselyConfiguration("com.wisely.highlight_spring4.ch3.annotation")
 8 public class DemoConfig {
 9 
10 }
配置類
 1 package com.wisely.highlight_spring4.ch3.annotation;
 2 
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 /**
 6  * 運行
 7  */
 8 public class Main {
 9     public static void main(String[] args) {
10         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DemoConfig.class);
11         DemoService demoService = context.getBean(DemoService.class);
12         demoService.outputResult();
13         context.close();
14     }
15 }
運行

測試

  簡介:

    測試是開發工做中不可缺乏的部分。單元測試只針對當前開發的類和方法進行測試,能夠簡單經過模擬依賴來實現,對運行環境沒有依賴;可是僅僅進行單元測試是不夠的,它只能驗證當前類或方法可否正常工做,而咱們想要知道系統的各個部分組合在一塊兒是否能正常工做,這就是集成測試存在的意義。

    集成測試通常須要來自不一樣層的不一樣對象的交互,如數據庫、網絡鏈接、IoC容器等。其實咱們也常常經過運行程序,而後經過本身操做來完成相似於集成測試的流程。集成測試爲咱們提供了一種無須部署或運行程序來完成驗證系統各部分是否能正常協同工做的能力。

    Spring經過Spring TestContex Framework對集成測試提供頂級支持。它不依賴於特定的測試框架,既能夠用Junit,也能夠用TestNG。

  例子:

 1 package com.wisely.highlight_spring4.ch3.fortest;
 2 
 3 /**
 4  * 測試Bean
 5  */
 6 public class TestBean {
 7 
 8     private String content;
 9 
10     public TestBean(String content) {
11         super();
12         this.content = content;
13     }
14 
15     public String getContent() {
16         return content;
17     }
18 
19     public void setContent(String content) {
20         this.content = content;
21     }
22 }
測試Bean
 1 package com.wisely.highlight_spring4.ch3.fortest;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Configuration;
 5 import org.springframework.context.annotation.Profile;
 6 
 7 /**
 8  * 測試配置類
 9  */
10 @Configuration
11 public class TestConfig {
12 
13     @Bean
14     @Profile("dev")
15     public TestBean devTestBean() {
16         return new TestBean("from development profile");
17     }
18 
19     @Bean
20     @Profile("prod")
21     public TestBean prodTestBean() {
22         return new TestBean("from production profile");
23     }
24 }
測試配置類
 1 package com.wisely.highlight_spring4.ch3.fortest;
 2 
 3 
 4 import org.junit.Assert;
 5 import org.junit.Test;
 6 import org.junit.runner.RunWith;
 7 import org.springframework.beans.factory.annotation.Autowired;
 8 import org.springframework.test.context.ActiveProfiles;
 9 import org.springframework.test.context.ContextConfiguration;
10 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
11 
12 /**
13  * 測試類
14  */
15 @RunWith(SpringJUnit4ClassRunner.class) //SpringJUnit4ClassRunner在JUnit環境下提供Spring TestContext Framework的功能。
16 @ContextConfiguration(classes = {TestConfig.class}) //@ContextConfiguration用來加載配置ApplicationContext,其中classes屬性用來加載配置類。
17 @ActiveProfiles("prod") //@ActiveProfiles用來聲明活動的profile。
18 public class DemoBeanIntegrationTests {
19 
20     @Autowired //可使用普通的@Autowired註解注入Bean。
21     private TestBean testBean;
22 
23     @Test //測試代碼,經過JUnit的Assert來校驗結果是否和預期一致。
24     public void prodBeanShouldInject() {
25         String expected = "from production profile";
26         String actual = testBean.getContent();
27         Assert.assertEquals(expected, actual);
28     }
29 }
測試類

 

@Enlable*註解

  簡介:

    在Spring中,大量的使用到了@Enlable*註解來開啓各類功能,避免了咱們本身配置大量的代碼,大大下降了使用難度。下面咱們來看一下它的實現原理。

    經過觀察這些@Enlable*註解的源碼,咱們發現全部的註解都有一個@Import註解,@Import是用來導入配置類的,這也就意味着這些自動開啓的實現實際上是導入了一些自動配置的Bean。

    這些導入的配置方式主要分爲如下三種類型。

  第一類:

    直接導入配置類。

 1 //
 2 // Source code recreated from a .class file by IntelliJ IDEA
 3 // (powered by Fernflower decompiler)
 4 //
 5 
 6 package org.springframework.scheduling.annotation;
 7 
 8 import java.lang.annotation.Documented;
 9 import java.lang.annotation.ElementType;
10 import java.lang.annotation.Retention;
11 import java.lang.annotation.RetentionPolicy;
12 import java.lang.annotation.Target;
13 import org.springframework.context.annotation.Import;
14 
15 @Target({ElementType.TYPE})
16 @Retention(RetentionPolicy.RUNTIME)
17 @Import({SchedulingConfiguration.class})
18 @Documented
19 public @interface EnableScheduling {
20 }

    直接導入配置類SchedulingConfiguration,這個類註解了@Configuration,且註冊了一個scheduledAnnotationProcessor的Bean,源碼以下。

 1 //
 2 // Source code recreated from a .class file by IntelliJ IDEA
 3 // (powered by Fernflower decompiler)
 4 //
 5 
 6 package org.springframework.scheduling.annotation;
 7 
 8 import org.springframework.context.annotation.Bean;
 9 import org.springframework.context.annotation.Configuration;
10 import org.springframework.context.annotation.Role;
11 
12 @Configuration
13 public class SchedulingConfiguration {
14     public SchedulingConfiguration() {
15     }
16 
17     @Bean(
18         name = {"org.springframework.context.annotation.internalScheduledAnnotationProcessor"}
19     )
20     @Role(2)
21     public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
22         return new ScheduledAnnotationBeanPostProcessor();
23     }
24 }

 

  第二類:

    依據條件選擇配置類。

 1 //
 2 // Source code recreated from a .class file by IntelliJ IDEA
 3 // (powered by Fernflower decompiler)
 4 //
 5 
 6 package org.springframework.scheduling.annotation;
 7 
 8 import java.lang.annotation.Annotation;
 9 import java.lang.annotation.Documented;
10 import java.lang.annotation.ElementType;
11 import java.lang.annotation.Retention;
12 import java.lang.annotation.RetentionPolicy;
13 import java.lang.annotation.Target;
14 import org.springframework.context.annotation.AdviceMode;
15 import org.springframework.context.annotation.Import;
16 
17 @Target({ElementType.TYPE})
18 @Retention(RetentionPolicy.RUNTIME)
19 @Documented
20 @Import({AsyncConfigurationSelector.class})
21 public @interface EnableAsync {
22     Class<? extends Annotation> annotation() default Annotation.class;
23 
24     boolean proxyTargetClass() default false;
25 
26     AdviceMode mode() default AdviceMode.PROXY;
27 
28     int order() default 2147483647;
29 }

    AsyncConfigurationSelector經過條件來選擇須要導入的配置類,AsyncConfigurationSelector的根接口爲ImportSelector,這個接口需重寫selectImports方法,在此方法中進行事先條件判斷。

    下面的源碼中,若adviceMode爲PORXY,則返回ProxyAsyncConfiguration這個配置類,若activeMode爲ASPECTJ,則返回AspectJAsyncConfiguration配置類。

 1 //
 2 // Source code recreated from a .class file by IntelliJ IDEA
 3 // (powered by Fernflower decompiler)
 4 //
 5 
 6 package org.springframework.scheduling.annotation;
 7 
 8 import org.springframework.context.annotation.AdviceMode;
 9 import org.springframework.context.annotation.AdviceModeImportSelector;
10 
11 public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
12     private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME = "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
13 
14     public AsyncConfigurationSelector() {
15     }
16 
17     public String[] selectImports(AdviceMode adviceMode) {
18         switch(adviceMode) {
19         case PROXY:
20             return new String[]{ProxyAsyncConfiguration.class.getName()};
21         case ASPECTJ:
22             return new String[]{"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration"};
23         default:
24             return null;
25         }
26     }
27 }

  第三類:

    動態註冊Bean。

 1 //
 2 // Source code recreated from a .class file by IntelliJ IDEA
 3 // (powered by Fernflower decompiler)
 4 //
 5 
 6 package org.springframework.context.annotation;
 7 
 8 import java.lang.annotation.Documented;
 9 import java.lang.annotation.ElementType;
10 import java.lang.annotation.Retention;
11 import java.lang.annotation.RetentionPolicy;
12 import java.lang.annotation.Target;
13 
14 @Target({ElementType.TYPE})
15 @Retention(RetentionPolicy.RUNTIME)
16 @Documented
17 @Import({AspectJAutoProxyRegistrar.class})
18 public @interface EnableAspectJAutoProxy {
19     boolean proxyTargetClass() default false;
20 }

    AspectJAutoProxyRegistrar實現了ImportBeanDefinitionRegistrar接口,ImportBeanDefinitionRegistrar的做用是在運行時自動添加Bean到已有的配置類,經過重寫方法:

 public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) 。

    其中,AnnotationMetadata參數用來得到當前配置類上的註解,BeanDefinitionRegistry參數用來註冊Bean。源碼以下:

 1 //
 2 // Source code recreated from a .class file by IntelliJ IDEA
 3 // (powered by Fernflower decompiler)
 4 //
 5 
 6 package org.springframework.context.annotation;
 7 
 8 import org.springframework.aop.config.AopConfigUtils;
 9 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
10 import org.springframework.core.annotation.AnnotationAttributes;
11 import org.springframework.core.type.AnnotationMetadata;
12 
13 class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
14     AspectJAutoProxyRegistrar() {
15     }
16 
17     public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
18         AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
19         AnnotationAttributes enableAJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
20         if (enableAJAutoProxy.getBoolean("proxyTargetClass")) {
21             AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
22         }
23 
24     }
25 }
相關文章
相關標籤/搜索