[TOC]html
模式註解是一種用於聲明在應用中扮演「組件」角色的註解。如 Spring Framework 中的 @Repository 標註在任何類上 ,用 於扮演倉儲角色的模式註解。java
模式註解(角色註解)web
Spring Framework 註解 | 場景說明 |
---|---|
@Component | 通用組件模式註解 |
@Controller | Web 控制器模式註解 |
@Service | 服務模式註解 |
@Repository | 數據倉儲模式註解 |
@Configuration | 配置類模式註解 |
在Spring中進行裝配context:component-scan 方式spring
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring- context.xsd"> <!-- 激活註解驅動特性 --> <context:annotation-config /> <!-- 找尋被 @Component 或者其派生 Annotation 標記的類(Class),將它們註冊爲 Spring Bean --> <context:component-scan base-package="com.imooc.dive.in.spring.boot" /> </beans>
在Spring中基於Java註解配置方式編程
@ComponentScan(basePackages = "com.imooc.dive.in.spring.boot") public class SpringConfiguration { ... }
@Component 模式註解具備「派生性」和「層次性」,咱們可以自定義建立Bean註解緩存
第一步:自定義SpringBean註解springboot
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface MyServiceAnnotation { String value() default ""; }
第二步:將註解做用在自定義Bean上框架
@MyServiceAnnotation(value = "testBean") public class TestBean { }
第三步:測試是否能夠從Spring容器中獲取到自定義Bean異步
@SpringBootApplication public class Main { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(Main.class, args); TestBean testBean = run.getBean("testBean", TestBean.class); System.out.println("testBean" + testBean.toString()); run.close(); } }
Spring Framework 3.1 開始支持」@Enable 模塊驅動「。所謂「模塊」是指具有相同領域的功能組件集合, 組合所造成一個獨立的單元。好比 Web MVC 模塊、AspectJ代理模塊、Caching(緩存)模塊、JMX(Java 管 理擴展)模塊、Async(異步處理)模塊等。ide
框架實現 | @Enable 註解模塊 | 激活模塊 |
---|---|---|
Spring Framework | @EnableWebMvc | Web MVC 模塊 |
Spring Framework | @EnableTransactionManagement | 事務管理模塊 |
Spring Framework | @EnableCaching | Caching 模塊 |
Spring Framework | @EnableMBeanExport | JMX 模塊 |
Spring Framework | @EnableAsync | 異步處理模塊 |
Spring Framework | @EnableWebFlux | Web Flux 模塊 |
Spring Framework | @EnableAspectJAutoProxy AspectJ | 代理模塊 |
Spring Boot | @EnableAutoConfiguration | 自動裝配模塊 |
Spring Boot | @EnableManagementContext | Actuator 管理模塊 |
Spring Boot | @EnableConfigurationProperties | 配置屬性綁定模塊 |
Spring Boot | @EnableOAuth2Sso | OAuth2 單點登陸模塊 |
...... |
第一步:實現自定義註解@EnableMyBean
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(MyBeanConfig.class) public @interface EnableMyBean { }
PS:注意@Import(MyBeanConfig.class),將導入MyBeanConfig配置類的相關Bean
第二步:建立MyBeanConfig配置類
@Configuration public class MyBeanConfig { @Bean(name = "hello") public String hello() { return "word"; } }
第三步:在應用中測試使用@EnableMyBean
@SpringBootApplication(scanBasePackages = "com.jimisun.learnspringboot.three") @EnableMyBean public class Main { public static void main(String[] args) { ConfigurableApplicationContext context = new SpringApplicationBuilder(Main.class) .web(WebApplicationType.NONE) .run(args); String bean = context.getBean("hello", String.class); context.close(); } }
第一步:實現自定義註解@EnableMyBean
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(MyBeanConfigSelector.class) public @interface EnableMyBean { }
PS:注意@Import(MyBeanConfigSelector.class)導入的類和@Enable註解驅動導入的不同,這裏導入的是一個實現了ImportSelector接口的類
public class MyBeanConfigSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{new MyBeanConfig().getClass().getName()}; } }
PS:在MyBeanConfigSelector類中咱們能夠自定義複雜的邏輯,這裏咱們僅僅簡單返回MyBeanConfig配置類。
第三步:建立MyBeanConfig配置類
@Configuration public class MyBeanConfig { @Bean public String hello() { return "word"; } }
第四步:在應用中測試使用@EnableMyBean
@SpringBootApplication(scanBasePackages = "com.jimisun.learnspringboot.four") @EnableMyBean public class Main { public static void main(String[] args) { ConfigurableApplicationContext context = new SpringApplicationBuilder(Main.class) .web(WebApplicationType.NONE) .run(args); String bean = context.getBean("hello", String.class); context.close(); } }
PS:其實@Enable接口的實現方式和@Enable註解實現方式是基本同樣的,只不過多了一個步驟,方便咱們更靈活地進行編寫邏輯。
從 Spring Framework 3.1 開始,容許在 Bean 裝配時增長前置條件判斷
Spring 註解 | 場景說明 | 起始版本 |
---|---|---|
@Profile | 配置化條件裝配 | 3.1 |
@Conditional | 編程條件裝配 | 4.0 |
第一步:自定義建立某服務不一樣的@Profile實現類
public interface UserService { void println(); }
@Service @Profile("vip") public class VipUserservice implements UserService { @Override public void println() { System.out.println("I am VIP User"); } }
@Service @Profile("common") public class CommonUserservice implements UserService { @Override public void println() { System.out.println("I am Common User"); } }
第二步:在構建Spring容器指定配置
@ComponentScan(basePackages = "com.jimisun.learnspringboot.two") public class Main { public static void main(String[] args) { ConfigurableApplicationContext run = new SpringApplicationBuilder(Main.class). web(WebApplicationType.NONE). profiles("vip"). run(args); UserService bean = run.getBean(UserService.class); bean.println(); run.close(); } }
第一步:建立一個自定義註解
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) @Documented @Conditional({MyOnConditionProperty.class}) public @interface MyConditionOnPropertyAnnotion { String prefix() default ""; }
PS:注意@Conditional註解,將會找到MyOnConditionProperty類的matches方法進行條件驗證
第二步:建立該註解的條件驗證類,該類實現Condition接口
public class MyOnConditionProperty implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { Map<String, Object> annotationAttributes = annotatedTypeMetadata.getAnnotationAttributes(MyConditionOnPropertyAnnotion.class.getName()); String prefix = String.valueOf(annotationAttributes.get("prefix")); return prefix.equals("pass"); } }
第三步:在Spring應用中應用條件裝配
@SpringBootApplication public class Main { @Bean(name = "hello") @MyConditionOnPropertyAnnotion(prefix = "pass") public String hello() { return "word"; } public static void main(String[] args) { ConfigurableApplicationContext context = new SpringApplicationBuilder(Main.class) .web(WebApplicationType.NONE) .run(args); String bean = context.getBean("hello", String.class); context.close(); } }
PS:本例自定義的MyConditionOnPropertyAnnotion在應用中裝配的時候能夠指定prefix值,該值將會在實現了Condition藉口的matches進行條件驗證,若是驗證經過,則在Spring容器中裝配該Bean,反之則不裝配。
在 Spring Boot 場景下,基於約定大於配置的原則,實現 Spring 組件自動裝配的目的。其中底層使用了一系列的Spring Framework手動裝配的方法來構成Spring Boot自動裝配。
第一步 :激活自動裝配 - @EnableAutoConfiguration
@EnableAutoConfiguration public class Main { public static void main(String[] args) { ConfigurableApplicationContext context = new SpringApplicationBuilder(Main.class) .web(WebApplicationType.NONE) .run(args); String bean = context.getBean("hello", String.class); context.close(); } }
第二步:實現自動裝配 - XXXAutoConfiguration
@Configuration @EnableMyBean public class HelloWordAutoConfiguration { }
PS:這裏使用了上面咱們建立的@EnableMyBean,這個註解會注入一個名爲「hello"的Bean
第三步:配置自動裝配實現 - META-INF/spring.factories
在ClassPath目錄下建立META-INF文件夾再建立spring.factories文件
#配置本身的自動裝配Bean org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.jimisun.learnspringboot.five.HelloWordAutoConfiguration
最後:運行測試第一步中的Main方法,看是否能獲取到名爲「hello」的Bean
本章咱們主要了解了Spring Framework的模式註解裝配,@Enable裝配和條件裝配。對於SpringBoot的自動裝配咱們僅僅作了一下演示,遵循SpringBoot裝配的三個步驟,咱們就能夠運行SpringBoot的自動裝配。可是對於SpringBoot爲何要遵循這三個步驟?自動裝配的原理?咱們不知因此然,因此下一章節咱們仍然以SpringBoot的自動裝配爲主題,對SpringBoot的底層源碼作剖析。
該教程所屬Java工程師之SpringBoot系列教程,本系列相關博文目錄 Java工程師之SpringBoot系列教程前言&目錄