springBoot @Enable*註解的工作原理
阿新 • • 發佈:2018-10-18
圖解 tor def sys autoconf 屬性註入 erb ota efi
使用註解實現異步
RunnableDemo類
package com.boot.enable.bootenable; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import java.util.concurrent.TimeUnit; @Component public class RunnableDemo implements Runnable { @Async // 異步方式執行方法 public voidrun() { for (int i = 0; i < 10; i++) { System.out.println("----------------"+ (i +1)); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } } }
測試類
packagecom.boot.enable.bootenable; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication @EnableAsyncpublic class BootEnableApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(BootEnableApplication.class, args); Runnable bean = context.getBean(Runnable.class); System.out.println("-----------start-----------"); bean.run(); System.out.println("-----------end-----------"); context.close(); } }
運行結果分析:
run方法打印的內容是異步進行的,是獨立於主線程外的線程,所以-----------end-----------打印後,run方法依然再進行打印
幾種裝配方式
1.普通的方式
package com.boot.enable.imp.demo; public class Book { }
package com.boot.enable.imp.demo; import org.springframework.stereotype.Component; @Component public class User { }
package com.boot.enable.imp.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; /** * 普通方式裝配 */ @SpringBootApplication public class ImportApplication { @Bean public Book book() { return new Book(); } public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(ImportApplication.class, args); System.out.println(context.getBean(User.class)); System.out.println(context.getBean(Book.class)); context.close(); } }
使用@Import裝配的第一種方式
package com.boot.enable.imp.demo1; public class Book { }
package com.boot.enable.imp.demo1; public class User { }
package com.boot.enable.imp.demo1; import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; public class BeanImportSelector implements ImportSelector {//不需要註入其他屬性時使用 @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{"com.boot.enable.imp.demo1.Book" ,"com.boot.enable.imp.demo1.User"}; } }
package com.boot.enable.imp.demo1; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Import; /** * 使用@Import方式裝配 */ @SpringBootApplication // @Import({User.class, Book.class}) @Import(BeanImportSelector.class) public class ImportApplication1 { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(ImportApplication1.class, args); System.out.println(context.getBean(User.class)); System.out.println(context.getBean(Book.class)); context.close(); } }
使用@Import裝配 第二種方式
package com.boot.enable.imp.demo2; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; public class MyBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {//有屬性註入時使用 @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // 創建構建器對象 BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(User.class); BeanDefinition beanDefinition = bdb.getBeanDefinition(); registry.registerBeanDefinition("user", beanDefinition); BeanDefinitionBuilder bdb1 = BeanDefinitionBuilder.rootBeanDefinition(Book.class); BeanDefinition beanDefinition1 = bdb1.getBeanDefinition(); registry.registerBeanDefinition("book", beanDefinition1); } }
package com.boot.enable.imp.demo2; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Import; /** * 使用@Import方式裝配 */ @SpringBootApplication @Import(MyBeanDefinitionRegistrar.class) public class ImportApplication1 { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(ImportApplication1.class, args); System.out.println(context.getBean("user",User.class)); System.out.println(context.getBean(Book.class)); context.close(); } }
實例演示:註解註冊監控器實現
實體類準備:
package com.boot.enable.sample.bean; import org.springframework.stereotype.Component; @Component public class Person { }
public class Person1 { }
package com.boot.enable.sample.bean; import org.springframework.stereotype.Component; @Component public class Person2 { }
package com.boot.enable.sample.vo; import org.springframework.stereotype.Component; @Component public class UserVO { }
自定義一個註解(借用@Import機制)
package com.boot.enable.sample; import org.springframework.context.annotation.Import; import java.lang.annotation.*; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(ScannerPackageRegistrar.class) public @interface EnableScanner { String[] packages(); }
package com.boot.enable.sample; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; import java.util.Arrays; import java.util.List; public class ScannerPackageRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { String[] attrs = (String[]) importingClassMetadata .getAnnotationAttributes(EnableScanner.class.getName()) .get("packages");//獲取到註解的packages屬性 List<String> packages = Arrays.asList(attrs); System.out.println(packages); BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(MyBeanDefinitionProcessor.class); bdb.addPropertyValue("packages", packages);//註入屬性 registry.registerBeanDefinition(MyBeanDefinitionProcessor.class.getName(), bdb.getBeanDefinition());//裝配到Spring容器中 } }
package com.boot.enable.sample; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import java.util.List; public class MyBeanDefinitionProcessor implements BeanPostProcessor { private List<String> packages; public List<String> getPackages() { return packages; } public void setPackages(List<String> packages) { this.packages = packages; } @Override//掃描出裝配到容器中的類並打印出對應實例 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { for (String pack : packages) { if (bean.getClass().getName().startsWith(pack)) { System.out.println("instance bean:"+bean.getClass().getName()); } } return bean; } }
測試類
package com.boot.enable.sample; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; /** * 普通方式裝配 */ @SpringBootApplication @EnableScanner(packages ={"com.boot.enable.sample.bean","com.boot.enable.sample.vo"}) // 啟用監控掃描類的註解 public class ScannerPackageApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(ScannerPackageApplication.class, args); context.close(); new ScannerPackageApplication().callFunction(new FunctionImpl());//回調演示 } interface Function { void hello(); } static class FunctionImpl implements Function { @Override public void hello() { System.out.println("調用了FunctionImpl->Hello方法"); } } public void callFunction(Function fun) {
//處理其他事 fun.hello(); //回調
//處理其他事 } }
打印結果(打印出註入到Spring容器中的實例,Person1未加註解,所以未打印)
監控器流程圖解
springBoot @Enable*註解的工作原理