Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 我想看一级毛片免费的,在线观看免费精品国产,一区二区日韩

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          Spring 中 @EnableXXX 注解的套路

          在 Spring 框架中有很多實(shí)用的功能,不需要寫(xiě)大量的配置代碼,只需添加幾個(gè)注解即可開(kāi)啟。 其中一個(gè)重要原因是那些 @EnableXXX 注解,它可以讓你通過(guò)在配置類加上簡(jiǎn)單的注解來(lái)快速地開(kāi)啟諸如事務(wù)管理(@EnableTransactionManagement)、Spring MVC(@EnableWebMvc)或定時(shí)任務(wù)(@EnableScheduling)等功能。這些看起來(lái)簡(jiǎn)單的注解語(yǔ)句提供了很多功能,但它們的內(nèi)部機(jī)制從表面上看卻不太明顯。 一方面,對(duì)于使用者來(lái)說(shuō)用這么少的代碼獲得這么多實(shí)用的功能是很好的,但另一方面,如果你不了解某個(gè)東西的內(nèi)部是如何工作的,就會(huì)使調(diào)試和解決問(wèn)題更加困難。

          設(shè)計(jì)目標(biāo)

          Spring 框架中那些 @EnableXXX 注解的設(shè)計(jì)目標(biāo)是允許用戶用最少的代碼來(lái)開(kāi)啟復(fù)雜使用的功能。 此外,用戶必須能夠使用簡(jiǎn)單的默認(rèn)值,或者允許手動(dòng)配置該代碼。最后,代碼的復(fù)雜性要向框架使用者隱藏掉。 簡(jiǎn)而言之,讓使用者設(shè)置大量的 Bean,并選擇性地配置它們,而不必知道這些 Bean 的細(xì)節(jié)(或真正被設(shè)置的內(nèi)容)。下面來(lái)看看具體的幾個(gè)例子:

          @EnableScheduling (導(dǎo)入一個(gè) @Configuration 類)

          首先要知道的是,@EnableXXX 注解并不神奇。實(shí)際上在 BeanFactory 中并不知道這些注解的具體內(nèi)容,而且在 BeanFactory 類中,核心功能和特定注解(如 @EnableWebMvc)或它們所存放的 jar 包(如 spring-web)之間沒(méi)有任何依賴關(guān)系。 讓我們看一下 @EnableScheduling,下面看看它是如何工作的。 定義一個(gè) SchedulingConfig 配置類,如下所示:

          @Configuration
          @EnableScheduling
          public class SchedulingConfig {
            // some bean in here
          }
          

          上面的內(nèi)容沒(méi)有什么特別之處。只是一個(gè)用 @EnableScheduling 注釋的標(biāo)準(zhǔn) Java 配置。@EnableScheduling 讓你以設(shè)定的頻率執(zhí)行某些方法。例如,你可以每 10 分鐘運(yùn)行 BankService.transferMoneyToMghio()。 @EnableScheduling 注解源碼如下:

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.RUNTIME)
          @Import(SchedulingConfiguration.class)
          @Documented
          public @interface EnableScheduling {
          
          }
          

          上面的 EnableScheduling 注解,我們可以看到它只是一個(gè)標(biāo)準(zhǔn)的類級(jí)注解(@Target/@Retention),應(yīng)該包含在 JavaDocs 中(@Documented),但是它有一個(gè) Spring 特有的注解(@Import)。 @Import 是將一切聯(lián)系起來(lái)的關(guān)鍵。 在這種情況下,由于我們的 SchedulingConfig 被注解為 @EnableScheduling,當(dāng) BeanFactory 解析文件時(shí)(內(nèi)部是ConfigurationClassPostProcessor 在解析它),它也會(huì)發(fā)現(xiàn) @Import(SchedulingConfiguration.class) 注解,它將導(dǎo)入該值中定義的類。 在這個(gè)注解中,就是 SchedulingConfiguration。

          這里導(dǎo)入是什么意思呢?在這種情況下,它只是被當(dāng)作另一個(gè) Spring Bean。 SchedulingConfiguration 實(shí)際上被注解為@Configuration,所以 BeanFactory 會(huì)把它看作是另一個(gè)配置類,所有在該類中定義的 Bean 都會(huì)被拉入你的應(yīng)用上下文,就像你自己定義了另一個(gè) @Configuration 類一樣。 如果我們檢查 SchedulingConfiguration,我們可以看到它只定義了一個(gè)Bean(一個(gè)Post Processor),它負(fù)責(zé)我們上面描述的調(diào)度工作,源碼如下:

          @Configuration
          @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
          public class SchedulingConfiguration {
          
          	@Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
          	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
          	public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
          		return new ScheduledAnnotationBeanPostProcessor();
          	}
          
          }
          

          也許你會(huì)問(wèn),如果想配置 SchedulingConfiguration 中定義的 bean 呢? 這里也只是在處理普通的Bean。 所以你對(duì)其它 Bean 所使用的機(jī)制也適用于此。 在這種情況下,ScheduledAnnotationBeanPostProcessor 使用一個(gè)標(biāo)準(zhǔn)的 Spring Bean 生命周期(postProcessAfterInitialization)來(lái)發(fā)現(xiàn)應(yīng)用程序上下文何時(shí)被刷新。 當(dāng)符合條件時(shí),它會(huì)檢查是否有任何 Bean 實(shí)現(xiàn)了 SchedulingConfigurer,如果有,就使用這些 Bean 來(lái)配置自己。 其實(shí)這一點(diǎn)并不明細(xì)(在 IDE 中也不太容易找到),但它與 BeanFactory 是完全分離的,而且是一個(gè)相當(dāng)常見(jiàn)的模式,一個(gè) Bean 被用來(lái)配置另一個(gè) Bean。 而現(xiàn)在我們可以把所有的點(diǎn)連接起來(lái),它(在某種程度上)很容易找到(你可以 Google 一下文檔或閱讀一下 JavaDocs)。

          @EnableTransactionManagement(導(dǎo)入一個(gè) ImportSelector)

          在上一個(gè)示例中,我們討論了像 @EnableScheduling 這樣的注解如何使用 @Import 來(lái)導(dǎo)入另一個(gè) @Configuration 類并使其所有的 Bean 對(duì)你的應(yīng)用程序可用(和可配置)。但是如果你想根據(jù)某些配置加載不同的 Bean 集,會(huì)發(fā)生什么呢? @EnableTransactionManagement 就是一個(gè)很好的例子。TransactioConfig 定義如下:

          @Configuration
          @EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
          public class TransactioConfig {
              // some bean in here
          } 
          

          再一次,上面沒(méi)有什么特別之處。只是一個(gè)用@EnableTransactionManagement注釋的標(biāo)準(zhǔn)Java配置。唯一與之前的例子有些不同的是,用戶為注釋指定了一個(gè)參數(shù)(mode=AdviceMode.ASPECTJ)。 @EnableTransactionManagement注解本身看起來(lái)像這樣。

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Import(TransactionManagementConfigurationSelector.class)
          public @interface EnableTransactionManagement {
          
          	boolean proxyTargetClass() default false;
          
          	AdviceMode mode() default AdviceMode.PROXY;
          
          	int order() default Ordered.LOWEST_PRECEDENCE;
          }
          

          和前面一樣,一個(gè)相當(dāng)標(biāo)準(zhǔn)的注解,盡管這次它有一些參數(shù)。 然而,正如前文提到,@Import 注解是將一切聯(lián)系在一起的關(guān)鍵,這一點(diǎn)再次得到證實(shí)。 但區(qū)別在于,這次我們導(dǎo)入的是 TransactionManagementConfigurationSelector 這個(gè)類,通過(guò)源碼可以發(fā)現(xiàn),其實(shí)它不是一個(gè)被 @Configuration 注解的類。 TransactionManagementConfigurationSelector 是一個(gè)實(shí)現(xiàn)ImportSelector 的類。 ImportSelector 的目的是讓你的代碼選擇在運(yùn)行時(shí)加載哪些配置類。 它有一個(gè)方法,接收關(guān)于注解的一些元數(shù)據(jù),并返回一個(gè)類名數(shù)組。 在這種情況下,TransactionManagementConfigurationSelector 會(huì)查看模式并根據(jù)模式返回一些類。其中的 selectImports 方法源碼如下:

          @Override
          protected String[] selectImports(AdviceMode adviceMode) {
           switch (adviceMode) {
             case PROXY:
               return new String[] {AutoProxyRegistrar.class.getName(),
                                    ProxyTransactionManagementConfiguration.class.getName()};
             case ASPECTJ:
               return new String[] {determineTransactionAspectClass()};
             default:
               return null;
           }
          }
          

          這些類中的大多數(shù)是 @Configuration(例如 ProxyTransactionManagementConfiguration),通過(guò)前文介紹我們知道它們會(huì)像前面一樣工作。 對(duì)于 @Configuration 類,它們被加載和配置的方式與我們之前看到的完全一樣。 所以簡(jiǎn)而言之,我們可以使用 @Import 和 @Configuration 類來(lái)加載一套標(biāo)準(zhǔn)的 Bean,或者使用 @Import 和 ImportSelector 來(lái)加載一套在運(yùn)行時(shí)決定的 Bean。

          @EnableAspectJAutoProxy (在 Bean 定義層導(dǎo)入)

          @Import 支持的最后一種情況,即當(dāng)你想直接處理 BeanRegistry(工廠)時(shí)。如果你需要操作Bean Factory或者在Bean定義層處理Bean,那么這種情況就適合你,它與上面的情況非常相似。 你的 AspectJProxyConfig 可能看起來(lái)像。

          @Configuration
          @EnableAspectJAutoProxy 
          public class AspectJProxyConfig {
            // some bean in here
          }
          

          再一次,上面定義沒(méi)有什么特別的東西。只是一個(gè)用 @EnableAspectJAutoProxy 注釋的標(biāo)準(zhǔn) Java 配置。 下面是@EnableAspectJAutoProxy 的源代碼。

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Import(AspectJAutoProxyRegistrar.class)
          public @interface EnableAspectJAutoProxy {
          
          	boolean proxyTargetClass() default false;
          
          	boolean exposeProxy() default false;
          }
          

          和前面一樣,@Import 是關(guān)鍵,但這次它指向 AspectJAutoProxyRegistrar,它既沒(méi)有 @Configuration 注解,也沒(méi)有實(shí)現(xiàn) ImportSelector 接口。 這次使用的是實(shí)現(xiàn)了 ImportBeanDefinitionRegistrar。 這個(gè)接口提供了對(duì) Bean 注冊(cè)中心(Bean Registry)和注解元數(shù)據(jù)的訪問(wèn),因此我們可以在運(yùn)行時(shí)根據(jù)注解中的參數(shù)來(lái)操作 Bean 注冊(cè)表。 如果你仔細(xì)看過(guò)前面的示例,你可以看到我們忽略的類也是 ImportBeanDefinitionRegistrar。 在 @Configuration 類不夠用的時(shí)候,這些類會(huì)直接操作 BeanFactory。

          所以現(xiàn)在我們已經(jīng)涵蓋了 @EnableXXX 注解使用 @Import 將各種 Bean 引入你的應(yīng)用上下文的所有不同方式。 它們要么直接引入一組 @Configuration 類,這些類中的所有 Bean 都被導(dǎo)入到你的應(yīng)用上下文中。 或者它們引入一個(gè) ImportSelector 接口實(shí)現(xiàn)類,在運(yùn)行時(shí)選擇一組 @Configuration 類并將這些 Bean 導(dǎo)入到你的應(yīng)用上下文中。 最后,他們引入一個(gè)ImportBeanDefinitionRegistrars,可以直接與 BeanFactory 在 BeanDefinition 級(jí)別上合作。

          結(jié)論

          總的來(lái)說(shuō),個(gè)人認(rèn)為這種將 Bean 導(dǎo)入應(yīng)用上下文的方法很好,因?yàn)樗箍蚣苁褂谜叩氖褂媚硞€(gè)功能非常容易。不幸的是,它模糊了如何找到可用的選項(xiàng)以及如何配置它們。 此外,它沒(méi)有直接利用 IDE 的優(yōu)勢(shì),所以很難知道哪些 Bean 正在被創(chuàng)建(以及為什么)。 然而,現(xiàn)在我們知道了 @Import 注解,我們可以使用 IDE 來(lái)挖掘一下每個(gè)注解及其相關(guān)的配置類,并了解哪些 Bean 正在被創(chuàng)建,它們?nèi)绾伪惶砑拥侥愕膽?yīng)用上下文中,以及如何配置它們。 希望對(duì)你有幫助~

          文章來(lái)自https://www.cnblogs.com/mghio/p/16297637.html

          Spring或Spring Boot中我們經(jīng)常會(huì)用到很多@EnableXXX 注解,加上這些注解之后我們就可以 ‘啟用’ 某一個(gè)功能,或者可以使用某些Bean,比如:

          @EnableAsync 使用異步執(zhí)行、

          @EnableTransactionManagement 啟用事務(wù)、

          @EnableAutoConfiguration 開(kāi)啟自動(dòng)裝配

          等等,那么你知道背后的原理是什么樣的嗎?本文簡(jiǎn)要窺探一下。

          原理

          無(wú)論是Spring內(nèi)建的,還是我們自定義的@Enable 模塊,基本就3種實(shí)現(xiàn)方式,其目標(biāo)都是將指定的類定位為Spring Bean:

          1. 導(dǎo)入類為@Configuration Class。
          2. 導(dǎo)入類為 ImportSelector實(shí)現(xiàn);
          3. 導(dǎo)入類為 ImportBeanDefinitionRegistrar實(shí)現(xiàn);

          實(shí)例1:

          引導(dǎo)類為 @Configuration ,聲明Enable注解

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Import(HelloworldConfiguration.class)
          public @interface EnableHelloWorld {
          }

          @Configuration Class中定義Bean

          @Configuration

          public class HelloworldConfiguration {

          @Bean

          public String helloWorld() {

          return "Hello, world";

          }

          }

          開(kāi)啟EnableHelloWorld注解,獲取 helloWorld Bean

          @Configuration@EnableHelloWorldpublic class EnableHelloWorldBootstrap {
          
              public static void main(String[] args) {
                  AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();       
                // 注冊(cè)當(dāng)前引導(dǎo)類(被@Configuration標(biāo)注)到Spring上下文        
                context.register(EnableHelloWorldBootstrap.class);        
                // 啟動(dòng)上下文        
                context.refresh();        
                // 獲取Bean        
                String helloWorld = context.getBean("helloWorld", String.class);       
                System.out.printf("helloWorld = %s \n", helloWorld);        
                // 關(guān)閉上下文        
                context.close();   
              }
          }

          執(zhí)行結(jié)果:

          helloWorld = Hello, world

          實(shí)例2:導(dǎo)入類為 ImportSelector實(shí)現(xiàn)

          public interface Server {
          
              void start();    
             void close();    
             enum ServerType {        HTTP,        TCP    }
          }
          @Target(ElementType.TYPE) 
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Import(ServerImportSelector.class)
          public @interface EnableServer {
              Server.ServerType type();
          } 

          根據(jù)注解屬性,選擇要定義的Bean

          public class ServerImportSelector implements ImportSelector {
              @Override    public String[] selectImports(AnnotationMetadata annotationMetadata) {
                  Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(EnableServer.class.getName());        
                  Server.ServerType serverType = (Server.ServerType)attributes.get("type");        
                  String[] importClassNames = new String[0];        
                  switch (serverType) {            
                    case HTTP:                
                      importClassNames = new String[]{HttpServer.class.getName()};                
                      break;            
                    case TCP:                
                      importClassNames = new String[]{TcpServer.class.getName()};               
                      break;       
                  }
                  return importClassNames;    
              }
          }

          啟用Server,獲取對(duì)應(yīng)的功能:

          @Configuration
          @EnableServer(type = Server.ServerType.TCP)
          public class EnableServerBootsrap {
              public static void main(String[] args) {
                  AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();       
                  context.register(EnableServerBootsrap.class);        
                  context.refresh();      
                  // 獲取Bean
                  Server server = context.getBean(Server.class);       
                  // 啟用功能
                  server.start();        
                  server.close();        
                  context.close();    
              }
          }

          執(zhí)行結(jié)果:

          TcpServer start ...

          TcpServer close ....

          實(shí)例3:

          導(dǎo)入類為 ImportBeanDefinitionRegistrar實(shí)現(xiàn)

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Import(ServerImportBeanDefinitionRegistrar.class)
          public @interface EnableServer {
              Server.ServerType type();
          }

          注冊(cè)Bean

          public class ServerImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
              @Override    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
                    ImportSelector importSelector = new ServerImportSelector();        // 篩選Class名稱集合        String[] selectedClassNames = importSelector.selectImports(importingClassMetadata);        // 創(chuàng)建Bean定義        Stream.of(selectedClassNames)
                          // 轉(zhuǎn)化為BeanDefinitionBuilder對(duì)象                .map(BeanDefinitionBuilder::genericBeanDefinition)
                          // 轉(zhuǎn)化為BeanDefinition                .map(BeanDefinitionBuilder::getBeanDefinition)
                          .forEach(beanDefinition -> {
                              // 注冊(cè)BeanDefinition到BeanDefinitionRegistry                    BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);                });    }
          }

          啟用Server,獲取對(duì)應(yīng)的功能:見(jiàn)實(shí)例2。

          內(nèi)建模塊

          Spring 內(nèi)建模塊

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Import(AsyncConfigurationSelector.class)
          public @interface EnableAsync {
          }

          Dubbo 內(nèi)建模塊

          @Target({ElementType.TYPE})
          @Retention(RetentionPolicy.RUNTIME)
          @Inherited@Documented
          @Import(DubboConfigConfigurationRegistrar.class)
          public @interface EnableDubboConfig {
          }

          具體實(shí)現(xiàn)可以看下源碼,都是相同的原理。

          、創(chuàng)建視圖 :

          CREATE VIEW [schema].[view_name] //[schema].[view_name] 視圖的名稱

          --WITH ENCRYPTION, SCHEMABINDING, VIEW_METADATA

          AS

          ///視圖需要執(zhí)行的查詢語(yǔ)句

          -- WITH CHECK OPTION

          GO

          2、創(chuàng)建索引

          CREATE NONCLUSTERED INDEX index_name //NONCLUSTERED 可選參數(shù) UNIQUE-唯一索引

          ON [schema].[owner_name] ( column_name ) // [schema].[owner_name] 數(shù)據(jù)庫(kù)表 //column_name 要?jiǎng)?chuàng)建索引的列名

          --WITH PAD_INDEX

          -- | FILLFACTOR = fillfactor

          -- | IGNORE_DUP_KEY

          -- | DROP_EXISTING

          -- | STATISTICS_NORECOMPUTE

          -- | SORT_IN_TEMPDB, .. as required

          -- ON filegroup

          GO

          3、查詢數(shù)據(jù)庫(kù)所有的序列

          SELECT * FROM sys.sequences

          4、將當(dāng)前序列的值初始化到我需要的值

          SELECT

          NEXT VALUE FOR dbo.S_住院_床位信息表_床位ID

          GO 61

          5、創(chuàng)建索引

          CREATE NONCLUSTERED INDEX index_company

          ON dbo.Company (ognName,parentId,sort )

          --WITH PAD_INDEX

          -- | FILLFACTOR = fillfactor

          -- | IGNORE_DUP_KEY

          -- | DROP_EXISTING

          -- | STATISTICS_NORECOMPUTE

          -- | SORT_IN_TEMPDB, .. as required

          -- ON filegroup

          GO

          CREATE NONCLUSTERED INDEX index_department

          ON dbo.Department( ognName,parentId,sort,head,c_head,branched )

          --WITH PAD_INDEX

          -- | FILLFACTOR = fillfactor

          -- | IGNORE_DUP_KEY

          -- | DROP_EXISTING

          -- | STATISTICS_NORECOMPUTE

          -- | SORT_IN_TEMPDB, .. as required

          -- ON filegroup

          GO

          CREATE NONCLUSTERED INDEX index_user

          ON dbo.[User] (account,password,sort,name,sex )

          --WITH PAD_INDEX

          -- | FILLFACTOR = fillfactor

          -- | IGNORE_DUP_KEY

          -- | DROP_EXISTING

          -- | STATISTICS_NORECOMPUTE

          -- | SORT_IN_TEMPDB, .. as required

          -- ON filegroup

          GO

          CREATE NONCLUSTERED INDEX index_userKey

          ON dbo.UserKey ( userId,ognId )

          --WITH PAD_INDEX

          -- | FILLFACTOR = fillfactor

          -- | IGNORE_DUP_KEY

          -- | DROP_EXISTING

          -- | STATISTICS_NORECOMPUTE

          -- | SORT_IN_TEMPDB, .. as required

          -- ON filegroup

          GO

          6、創(chuàng)建觸發(fā)器

          ---單位觸發(fā)器

          CREATE TRIGGER trigger_Upate_Company

          ON dbo.Company

          AFTER UPDATE

          AS

          BEGIN

          IF (SELECT enable FROM Deleted)=0

          BEGIN

          UPDATE dbo.Department SET enable=0 WHERE parentId IN(SELECT Deleted.ognId FROM Deleted)

          END


          主站蜘蛛池模板: 国模极品一区二区三区| 日韩精品无码一区二区三区不卡| | 亚洲国产精品一区二区成人片国内| 无码AV中文一区二区三区| 国产精品资源一区二区| 国产成人精品第一区二区| 无码国产精品一区二区免费16 | 丝袜美腿高跟呻吟高潮一区| 亚洲电影唐人社一区二区| 国产婷婷色一区二区三区| 国产精品亚洲一区二区三区| 久久久无码精品人妻一区| 亚洲字幕AV一区二区三区四区| 国产精品免费一区二区三区四区| 精品国产一区二区三区在线观看| 国模精品视频一区二区三区| 亚洲色偷精品一区二区三区| 精品一区二区三区在线播放视频| 亚洲综合无码一区二区| 天堂国产一区二区三区| 亚洲综合无码AV一区二区 | 久久久久人妻一区精品| 一区二区免费电影| 一区二区三区四区精品| 国产精品一区12p| 真实国产乱子伦精品一区二区三区| 国产一区二区三区夜色| 国产视频一区二区在线播放| 亚洲国产成人一区二区精品区| 久久精品一区二区三区四区| 亚洲综合一区二区| 竹菊影视欧美日韩一区二区三区四区五区| 精品少妇一区二区三区视频| 日韩免费无码视频一区二区三区| 亚洲乱码一区av春药高潮| 亚洲精品伦理熟女国产一区二区| 无码人妻av一区二区三区蜜臀| 无码人妻av一区二区三区蜜臀 | 国产免费一区二区三区不卡| 国产午夜精品免费一区二区三区|