国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【深入淺出Spring原理及實戰(zhàn)】「夯實基礎(chǔ)系列」360全方位滲透和探究Spring的核心注解開發(fā)和實現(xiàn)指南(Spring5的常見的注解)

這篇具有很好參考價值的文章主要介紹了【深入淺出Spring原理及實戰(zhàn)】「夯實基礎(chǔ)系列」360全方位滲透和探究Spring的核心注解開發(fā)和實現(xiàn)指南(Spring5的常見的注解)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

Spring的注解介紹

Spring 5.x中常見的注解包括@Controller、@Service、@Repository。當(dāng)我們研究Spring Boot源碼時,會發(fā)現(xiàn)實際上提供了更多的注解。了解這些注解對于我們非常重要,盡管目前可能還用不到它們。

核心基礎(chǔ)注解

注解 功能
@Bean 器中注冊組件,代替來的標(biāo)簽
@Configuration 聲明這是一個配置類,替換以前的配置xml文件
@ComponentScan 包掃描,掃描@Controller、@Service、@Repository、@Component注入Spring容器中
@Conditional 按條件注入
@Primary 同類組件如果多個,標(biāo)注主組件
@Lazy 組件懶加載(最后使用的時候才創(chuàng)建)
@Scope 聲明組件的作用范圍(SCOPE_PROTOTYPE, SCOPE_SINGLETON)
@DependsOn 組件之間聲明依賴關(guān)系
@Component @Controller、@Service、@Repository的通用注解
@Indexed 加速注解,所有標(biāo)注了 @Indexed 的組件直接會啟動快速加載
@Order 數(shù)字越小優(yōu)先級越高,越先工作
@Import 導(dǎo)入第三方JAR包中的組,或定制批量導(dǎo)入組件邏
@ImportResource 導(dǎo)入以前的XML配置文件,讓其生效
@Profile 基于多環(huán)境激活
@PropertySource 外部properties配置文件和JavaBean進行綁定,結(jié)合ConfigurationProperties
@PropertySources @PropertySource組合注解
@Autowired 自動裝
@Qualifier 精確指定
@Value 取值、計算機環(huán)境變量、JVM系統(tǒng)。@Value(“$”)
@Lookup 單例組件依賴非單例組件,非單例組件獲取需要使用方法

注意:@Indexed 需要引入依賴org.springframework spring-context-indexer true

核心注解分析

【深入淺出Spring原理及實戰(zhàn)】「夯實基礎(chǔ)系列」360全方位滲透和探究Spring的核心注解開發(fā)和實現(xiàn)指南(Spring5的常見的注解),# 深入淺出Spring源碼及原理實戰(zhàn),spring,java,后端### @Configuration和@Bean

在早期的Spring項目中,我們通常需要創(chuàng)建一個名為springContext.xml的配置文件,并通過標(biāo)簽進行注入。然而,通過使用 @Configuration 注解,我們可以將一個普通的Java類充當(dāng)配置文件,取代了繁瑣的xml配置。而使用 @Bean 注解則可以替代原來的 標(biāo)簽。

xml文件的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="beanSample" class="com.xxx.xxx.BeanSample"></bean>
</beans>
configuration的配置
@Configuration
public class SpringConfig {
    @Bean("beanSample")
    BeanSample beanSample() {
        return new BeanSample ();
    }
}

public class SpringTest {
    @Test
    public void beanSample() {
        // 通過配置文件的方式獲取所有的bean
        ApplicationContext context = new ClassPathXmlApplicationContext("springContext.xml");
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println("xml=>" + beanDefinitionName);
        }
        // 最后打?。簒ml=>user
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        String[] beanDefinitionName = annotationConfigApplicationContext.getBeanDefinitionNames();
        for (String name : beanDefinitionName) {
            System.out.println("annotation = > " + name);
        }
        // 最后打印去處默認配置后:
        // annotation = > springConfig
		// annotation = > beanSample
    }
}

注意:@Bean配置的時候,方法名為默認的id類型,當(dāng)然也可以@Bean(“id”)這樣來指定id。另外,@Bean注入的對象默認都是單例的。

@Lazy && @Scope

如前所述,通過使用@Bean注解,我們可以將對象直接注冊到容器中。那么如何設(shè)置注冊的對象為原型作用域呢?是否可以進行懶加載呢?

首先,要將注冊的對象設(shè)置為原型作用域,只需要在 @Bean 注解上添加 @Scope(“prototype”) 即可。這樣,每次從容器中獲取該對象時,都會創(chuàng)建一個新的實例。

// SpringConfig.class
/**
 * @Scope可選內(nèi)容為:
 * ConfigurableBeanFactory#SCOPE_PROTOTYPE  原型模式
 * ConfigurableBeanFactory#SCOPE_SINGLETON  單例模式
 * org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request模式,同一次強求一個對象
 * org.springframework.web.context.WebApplicationContext#SCOPE_SESSION session模式,同一個session一個對象
 */
@Bean("beanSample")
@Scope("prototype")
BeanSample beanSample() {
	return new BeanSample ();
}

@Bean("beanSample2")
@Scope("singleton")
BeanSample beanSample2() {
	return new BeanSample();
}

// SpringTest.class
BeanSample beanSample = (BeanSample ) annotationConfigApplicationContext.getBean("beanSample");
BeanSample beanSample2 = (BeanSample ) annotationConfigApplicationContext.getBean("beanSample2");
/**
 * 當(dāng)@Scope("singleton")時,為false
 * 當(dāng)@Scope("prototype")時,為true
 */
System.out.println(beanSample == beanSample2 ); 

懶加載的支持需要根據(jù)具體情況進行配置。默認情況下,使用 @Bean 注解注冊的對象是在容器啟動時就初始化的,即默認是立即加載的。@Lazy只是在單例模式下使用,讓對象需要創(chuàng)建的時候才注入到容器。

如果希望將其設(shè)置為懶加載,可以在 @Bean 注解上添加 @Lazy 注解。通過 @Bean 注解不僅可以注冊對象到容器中,還可以方便地設(shè)置對象的作用域和加載策略。

@ComponentScan

在最早使用Spring項目時,我們不需要將 @Controller、@Service、@Repository 這些注解添加到Spring容器中。為了將這些類加載到Spring容器中,我們通常使用了一個包掃描的配置。使用<context:component-scan base-package="com.xxx"> 這個注解來掃描指定包下的類,將其加載到Spring容器中。

@ComponentScan注解相當(dāng)于 <context:component-scan> 注解,它能夠自動掃描指定包及其子包下的類,并將其注冊到Spring容器中。

添加Controller、Service、Repository
@Controller
public class UserController {}
@Service
public class UserService {}
@Repository
public class UserDao {}
注入到spring容器

在SpringConfig的類上添加 @ComponentScan(value = “com.xxx”),Controller、Service、Dao也注入到spring容器中了使用 @ComponentScan 注解可以方便地配置要掃描的包,并將注解類自動加載到Spring容器中。

@ComponentScan多包掃描的屬性

當(dāng)你想掃描多個包的時候,你可以配置value為一個數(shù)組。

@ComponentScan(value = {"com.xxx.a", "com.xxx.b"})
排除某些包或者類的掃描

如果你不想讓某個包或注解被掃描到,可以在 @ComponentScan 注解中使用 excludeFilters 屬性。

在 excludeFilters 中,有幾種常見的 Filter 類型可供選擇:

  • FilterType.ANNOTATION:根據(jù)注解類型進行過濾
  • FilterType.ASSIGNABLE_TYPE:根據(jù)給定的類型進行過濾
  • FilterType.CUSTOM:自定義過濾規(guī)則

利用這些 Filter 類型,你可以靈活地控制應(yīng)該排除哪些包或注解,從而更好地管理 Spring 容器中的組件。

排除過濾:FilterType.ANNOTATION

可以使用@ComponentScan注解的excludeFilters 屬性來幫助你排除特定的注解。對于你的需求,你可以使用 FilterType.ANNOTATION 類型的過濾器,掃描 com.bearjun 包時排除 @Controller 注解。

具體的實現(xiàn)可以如下所示:

@Configuration
@ComponentScan(
    basePackages = "com.xxx",
    excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class)
)

在上面的例子中,我們使用了 @ComponentScan 注解來指定需要掃描的基礎(chǔ)包為 com.xxx,并使用 excludeFilters 屬性來配置過濾器。在過濾器中,我們指定了類型為 FilterType.ANNOTATION,值為 Controller.class,表示要排除所有帶有 @Controller 注解的組件。

這樣配置之后,Spring 在進行組件掃描時就會排除掉 com.xxx包中帶有 @Controller 注解的組件

排除過濾:FilterType.ASSIGNABLE_TYPE

可以使用 @ComponentScan 注解的 excludeFilters 屬性來幫助你排除特定的類。對于你的需求,你可以使用 FilterType.ASSIGNABLE_TYPE 類型的過濾器,掃描 com.xxx 包時排除 TestSample 類。

@Configuration
@ComponentScan(
    basePackages = "com.xxx",
    excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = TestSample.class)
)

在上面的例子中,我們使用了 @ComponentScan 注解來指定需要掃描的基礎(chǔ)包為 com.xxx,并使用 excludeFilters 屬性來配置過濾器。在過濾器中,我們指定了類型為 FilterType.ASSIGNABLE_TYPE,值為 TestSample.class,表示要排除 TestSample 類。

這樣配置之后,Spring 在進行組件掃描時就會排除掉 com.xxx 包中的 TestSample 類。

排除過濾:FilterType.CUSTOM

使用 @ComponentScan 注解的 excludeFilters 屬性來幫助你根據(jù)自定義的過濾器來排除特定的組件。在這個過程中,你需要實現(xiàn)一個自定義的過濾器 MyFilter,然后根據(jù)過濾的邏輯返回 true 或 false。

具體的實現(xiàn)可以如下所示:

@Configuration
@ComponentScan(value = {"com.xxx"}, excludeFilters = {
        @ComponentScan.Filter(type = FilterType.CUSTOM, value = MyFilter.class)
})
  • 下面是一個示例的自定義過濾器 MyFilter 的實現(xiàn):
// FilterType.CUSTOM類型。
// 自定義一個類,實現(xiàn) org.springframework.core.type.filter.TypeFilter;
public class MyFilter implements TypeFilter {
    /**
     * @param metadataReader 當(dāng)前正在掃描的類 ComponentScan value的值的信息
     * @param metadataReaderFactory 獲取其他類的信息
     * @return
     */
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) {
        // 當(dāng)前類的注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        // 當(dāng)前的掃描的類信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        // 當(dāng)前類資源
        Resource resource = metadataReader.getResource();
        String className = classMetadata.getClassName();
        // 所有的 controller 返回 true
        if (className.toLowerCase().contains("controller")) {
            return true;
        }
        return false;
    }
}

在上述的示例中,我們使用了 @ComponentScan 注解來指定需要掃描的基礎(chǔ)包為 com.xxx,并使用 excludeFilters 屬性配置了一個 TYPE 類型為 CUSTOM 的過濾器。過濾器的值為自定義的 MyFilter 類。

在 MyFilter 類中,我們實現(xiàn)了 TypeFilter 接口,并在 match 方法中編寫了過濾的邏輯。在示例中的邏輯中,我們判斷類名是否以 “Sample” 結(jié)尾,如果是,則返回 true,表示要過濾掉該組件。

這樣配置之后,Spring 在進行組件掃描時將掃描 com.xxx 包,但根據(jù) MyFilter 的邏輯,滿足過濾條件的組件將被排除掉。

@Conditional

使用 @Conditional 注解可以根據(jù)一定的條件進行判斷,只有滿足條件的情況下才會將 Bean 注入到 Spring 容器。

@Configuration
public class SpringConfig {
    @Bean("beanSample")
    BeanSample beanSample() {
        return new BeanSample ();
    }
    @Bean("beanSample2")
    @Conditional(BeanSampleCondition.class)
    BeanSample beanSample2() {
        return new BeanSample ();
    }
}

進行實現(xiàn)對應(yīng)的判斷邏輯條件處理方式。我們定義了 BeanSampleCondition條件類,它們實現(xiàn)了 Condition 接口,并重寫了 matches 方法。

public class BeanSampleCondition implements Condition {
    /**
     * @param context  上下文(可以獲取各種需要的信息)
     * @param metadata 注釋信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        /**
         * 獲取bean的注冊信息,可以新增,移除,判斷。。bean
         */
        BeanDefinitionRegistry registry = context.getRegistry();
        /**
         * 獲取項目運行的環(huán)境
         */
        Environment environment = context.getEnvironment();
        /**
         * 獲取bean工廠
         */
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        /**
         * 獲取類加載器活資源加載器
         */
        ClassLoader classLoader = context.getClassLoader();
        ResourceLoader resourceLoader = context.getResourceLoader();
        /**
         * 如果項目中是否存在一個bean叫bear
         */
        return context.getRegistry().containsBeanDefinition("beanSample2");
    }
}

根據(jù)系統(tǒng)的操作系統(tǒng)名稱我們可以定義我們的判斷邏輯,比如示例中判斷是否包含 “beanSample2” 命名的bean對象,如果滿足條件,則返回 true,表示這個條件成立,對應(yīng)的 Bean 將被注入到 Spring 容器。根據(jù)條件判斷,Spring 在初始化時會根據(jù)條件的結(jié)果來判斷是否將對應(yīng)的 Bean 注入到 Spring 容器。

@Test
public void test1() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    Map<String, User> beansOfType = context.getBeansOfType(User.class);
    beansOfType.forEach((key, value)->{
        System.out.println(key + " ==== " + value);
    });
}

最后輸出的結(jié)果為:

beanSample ==== BeanSample{}
beanSample2 ==== BeanSample{}

如果我們把@Bean(“beanSample2”)換成@Bean(“beanSample3”),最后的結(jié)果為:

beanSample ==== BeanSample{}

@Import

使用 @Import 注解可以引入其他配置類,并將其配置的 Bean 注冊到容器中。主要有三種方式分別是一下:

@Import +普通組件類
@Configuration
@ComponentScan(value = "com.bearjun")
@Import(value = {String.class, Math.class})
public class SpringConfig {

}
@Test
public void test3() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    String[] beanDefinitionName = context.getBeanDefinitionNames();
    for (String name : beanDefinitionName) {
    	System.out.println("annotation = > " + name);
	}
}

結(jié)果打印存在

annotation = > java.lang.String
annotation = > java.lang.Math
@Import(value=“ImportSelector.class”)
@Configuration
@ComponentScan(value = "com.bearjun")
@Import(value = {MyImportSelector.class})
public class SpringConfig {

}

public class MyImportSelector implements ImportSelector {
    /**
     * @param importingClassMetadata 獲取標(biāo)注了當(dāng)前@Import注解的所以注解信息
     * @return
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"java.lang.String"};
    }
}

@Test
public void test3() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    String[] beanDefinitionName = context.getBeanDefinitionNames();
    for (String name : beanDefinitionName) {
    	System.out.println("annotation = > " + name);
	}
}

結(jié)果打印存在

annotation = > java.lang.String
@Import(value=“ImportBeanDefinitionRegistrar.class”)
@Configuration
@ComponentScan(value = "com.bearjun")
@Import(value = {ImportBeanDefinitionRegistrar.class})
public class SpringConfig {

}

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * @param importingClassMetadata 當(dāng)前類的注解信息
     * @param registry               BeanDefinition注冊類
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        // bean注冊器中是否存在bearjun的組件
        if (registry.containsBeanDefinition("bearjun")) {
        	// 往組件中添加id為string的組件
        	BeanDefinition definition = new RootBeanDefinition("java.lang.String");
            registry.registerBeanDefinition("string", definition);
        }
    }
}

@Test
public void test3() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    String[] beanDefinitionName = context.getBeanDefinitionNames();
    for (String name : beanDefinitionName) {
    	System.out.println("annotation = > " + name);
	}
}

結(jié)果打印存在

annotation = > java.lang.String

@Lookup

單例組件依賴非單例組件,可以通過調(diào)用非單例組件的方法來獲取。

  • 使用@Lookup注解時,應(yīng)將其放置在獲取bean的方法上才能生效。
  • 從配置類中返回的bean不能作為單例模式組件(如上述的User類),否則@Lookup注解將不會生效。
@Component
@Scope("prototype")
public class Car {
    private String brand;
    // 省略get/set/toString
}

@Component
public class User {

    private Integer userId;
    private String username;
    private String password;
    private Car car;
    @Lookup
    public Car getCar() {
        return car;
    }
    public void setCar(Car car) {
        this.car = car;
    }
}

// SpringTest#test3
@Test
public void test3() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    User user1 = (User) context.getBean("user");
    User user2 = (User) context.getBean("user");
    System.out.println(user1 == user2);
    // 打印:true
    Car car1 = user1.getCar();
    Car car2 = user2.getCar();
    System.out.println(car1 == car2);
}

如果user#getCar不加@Lookup注解,打印為true,加@Lookup注解,打印為false文章來源地址http://www.zghlxwxcb.cn/news/detail-572816.html

到了這里,關(guān)于【深入淺出Spring原理及實戰(zhàn)】「夯實基礎(chǔ)系列」360全方位滲透和探究Spring的核心注解開發(fā)和實現(xiàn)指南(Spring5的常見的注解)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包