自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

聊聊Spring中的各項(xiàng)注解

開(kāi)發(fā) 架構(gòu)
作者個(gè)人研發(fā)的在高并發(fā)場(chǎng)景下,提供的簡(jiǎn)單、穩(wěn)定、可擴(kuò)展的延遲消息隊(duì)列框架,具有精準(zhǔn)的定時(shí)任務(wù)和延遲隊(duì)列處理功能。

[[385848]]

作者個(gè)人研發(fā)的在高并發(fā)場(chǎng)景下,提供的簡(jiǎn)單、穩(wěn)定、可擴(kuò)展的延遲消息隊(duì)列框架,具有精準(zhǔn)的定時(shí)任務(wù)和延遲隊(duì)列處理功能。自開(kāi)源半年多以來(lái),已成功為十幾家中小型企業(yè)提供了精準(zhǔn)定時(shí)調(diào)度方案,經(jīng)受住了生產(chǎn)環(huán)境的考驗(yàn)。為使更多童鞋受益,現(xiàn)給出開(kāi)源框架地址:https://github.com/sunshinelyz/mykit-delay

寫(xiě)在前面

由于在更新其他專(zhuān)題的文章,Spring系列文章有很長(zhǎng)一段時(shí)間沒(méi)有更新了,很多小伙伴都在公眾號(hào)后臺(tái)留言或者直接私信我微信催更Spring系列文章。

看來(lái)是要繼續(xù)更新Spring文章了。想來(lái)想去,寫(xiě)一篇關(guān)于Spring中注解相關(guān)的文章吧,因?yàn)橹案耂pring系列的文章一直也是在更新Spring注解驅(qū)動(dòng)開(kāi)發(fā)。這篇文章也算是對(duì)之前文章的一個(gè)小小的總結(jié)吧,估計(jì)更新完這篇,我們會(huì)進(jìn)入Spring的AOP章節(jié)的更新。

文章已收錄到:

https://github.com/sunshinelyz/technology-binghe

https://gitee.com/binghe001/technology-binghe

xml配置與類(lèi)配置

1.xml配置

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/sp 
  5.  <bean id="person" class="com.binghe.spring.Person"></bean> 
  6. </beans> 

獲取Person實(shí)例如下所示。

  1. public static void main( String[] args ){ 
  2.  ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); 
  3.  System.out.println(ctx.getBean("person")); 

2.類(lèi)配置

  1. @Configuration 
  2. public class MainConfig { 
  3.     @Bean 
  4.     public Person person(){ 
  5.      return new Person(); 
  6.     } 
  7. }   

這里,有一個(gè)需要注意的地方:通過(guò)@Bean的形式是使用的話, bean的默認(rèn)名稱(chēng)是方法名,若@Bean(value="bean的名稱(chēng)")那么bean的名稱(chēng)是指定的 。

獲取Person實(shí)例如下所示。

  1. public static void main( String[] args ){ 
  2.  AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class); 
  3.  System.out.println(ctx.getBean("person")); 

@CompentScan注解

我們可以使用@CompentScan注解來(lái)進(jìn)行包掃描,如下所示。

  1. @Configuration 
  2. @ComponentScan(basePackages = {"com.binghe.spring"}) 
  3.  public class MainConfig { 
  4. }  

excludeFilters 屬性

當(dāng)我們使用@CompentScan注解進(jìn)行掃描時(shí),可以使用@CompentScan注解的excludeFilters 屬性來(lái)排除某些類(lèi),如下所示。

  1. @Configuration 
  2. @ComponentScan(basePackages = {"com.binghe.spring"},excludeFilters = { 
  3. @ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class}), 
  4. @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {PersonService.class}) 
  5. }) 
  6. public class MainConfig { 

includeFilters屬性

當(dāng)我們使用@CompentScan注解進(jìn)行掃描時(shí),可以使用@CompentScan注解的includeFilters屬性將某些類(lèi)包含進(jìn)來(lái)。這里需要注意的是:需要把useDefaultFilters屬性設(shè)置為false(true表示掃描全部的)

  1. @Configuration 
  2. @ComponentScan(basePackages = {"com.binghe.spring"},includeFilters = { 
  3. @ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class, PersonService.class}) 
  4. },useDefaultFilters = false
  5. public class MainConfig { 

@ComponentScan.Filter type的類(lèi)型

注解形式的FilterType.ANNOTATION @Controller @Service @Repository @Compent

  • 指定類(lèi)型的 FilterType.ASSIGNABLE_TYPE @ComponentScan.Filter(type =FilterType.ASSIGNABLE_TYPE,value = {Person.class})
  • aspectj類(lèi)型的 FilterType.ASPECTJ(不常用)
  • 正則表達(dá)式的 FilterType.REGEX(不常用)
  • 自定義的 FilterType.CUSTOM
  1. public enum FilterType { 
  2.     //注解形式 比如@Controller @Service @Repository @Compent 
  3.     ANNOTATION, 
  4.     //指定的類(lèi)型 
  5.     ASSIGNABLE_TYPE, 
  6.     //aspectJ形式的 
  7.     ASPECTJ, 
  8.     //正則表達(dá)式的 
  9.     REGEX, 
  10.     //自定義的 
  11.     CUSTOM 

FilterType.CUSTOM 自定義類(lèi)型

  1. public class CustomFilterType implements TypeFilter { 
  2. @Override 
  3. public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { 
  4.     //獲取當(dāng)前類(lèi)的注解源信息 
  5.     AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); 
  6.     //獲取當(dāng)前類(lèi)的class的源信息 
  7.     ClassMetadata classMetadata = metadataReader.getClassMetadata(); 
  8.     //獲取當(dāng)前類(lèi)的資源信息 
  9.     Resource resource = metadataReader.getResource(); 
  10.   return classMetadata.getClassName().contains("Service"); 
  11.      
  12. @ComponentScan(basePackages = {"com.binghe.spring"},includeFilters = { 
  13. @ComponentScan.Filter(type = FilterType.CUSTOM,value = CustomFilterType.class) 
  14. },useDefaultFilters = false
  15. public class MainConfig { 

配置Bean的作用域?qū)ο?/strong>

不指定@Scope

在不指定@Scope的情況下,所有的bean都是單實(shí)例的bean,而且是餓漢加載(容器啟動(dòng)實(shí)例就創(chuàng)建好了)

  1. @Bean 
  2. public Person person() { 
  3.  return new Person(); 
  4. }  

@Scope為 prototype

指定@Scope為 prototype 表示為多實(shí)例的,而且還是懶漢模式加載(IOC容器啟動(dòng)的時(shí)候,并不會(huì)創(chuàng)建對(duì)象,而是在第一次使用的時(shí)候才會(huì)創(chuàng)建)

  1. @Bean 
  2. @Scope(value = "prototype"
  3. public Person person() { 
  4.     return new Person(); 

@Scope取值

  • singleton 單實(shí)例的(默認(rèn))
  • prototype 多實(shí)例的
  • request 同一次請(qǐng)求
  • session 同一個(gè)會(huì)話級(jí)別

懶加載

Bean的懶加載@Lazy(主要針對(duì)單實(shí)例的bean 容器啟動(dòng)的時(shí)候,不創(chuàng)建對(duì)象,在第一次使用的時(shí)候才會(huì)創(chuàng)建該對(duì)象)

  1. @Bean 
  2. @Lazy 
  3. public Person person() { 
  4.  return new Person(); 

@Conditional條件判斷

場(chǎng)景,有二個(gè)組件CustomAspect 和CustomLog ,我的CustomLog組件是依賴(lài)于CustomAspect的組件 應(yīng)用:自己創(chuàng)建一個(gè)CustomCondition的類(lèi) 實(shí)現(xiàn)Condition接口

  1. public class CustomCondition implements Condition { 
  2. /**** 
  3. @param context 
  4. * @param metadata 
  5. * @return 
  6. */ 
  7.     @Override 
  8.     public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { 
  9.         //判斷容器中是否有CustomAspect的組件 
  10.         return context.getBeanFactory().containsBean("customAspect"); 
  11.     }  
  12. }  
  13.  
  14. public class MainConfig { 
  15.     @Bean 
  16.     public CustomAspect customAspect() { 
  17.         return new CustomAspect(); 
  18.     }  
  19.     @Bean 
  20.     @Conditional(value = CustomCondition.class) 
  21.     public CustomLog customLog() { 
  22.      return new CustomLog(); 
  23.     } 

向IOC 容器添加組件

(1)通過(guò)@CompentScan +@Controller @Service @Respository @compent。適用場(chǎng)景: 針對(duì)我們自己寫(xiě)的組件可以通過(guò)該方式來(lái)進(jìn)行加載到容器中。

(2)通過(guò)@Bean的方式來(lái)導(dǎo)入組件(適用于導(dǎo)入第三方組件的類(lèi))

(3)通過(guò)@Import來(lái)導(dǎo)入組件 (導(dǎo)入組件的id為全類(lèi)名路徑)

  1. @Configuration 
  2. @Import(value = {Person.class}) 
  3. public class MainConfig { 

通過(guò)@Import 的ImportSeletor類(lèi)實(shí)現(xiàn)組件的導(dǎo)入 (導(dǎo)入組件的id為全類(lèi)名路徑)

  1. public class CustomImportSelector implements ImportSelector {  
  2.     @Override 
  3.     public String[] selectImports(AnnotationMetadata importingClassMetadata) { 
  4.      return new String[]{"com.binghe.spring"}; 
  5.     } 
  6. }  
  7. Configuration 
  8. @Import(value = {Person.class} 
  9. public class MainConfig { 

通過(guò)@Import的 ImportBeanDefinitionRegister導(dǎo)入組件 (可以指定bean的名稱(chēng))

  1. public class DogBeanDefinitionRegister implements ImportBeanDefinitionRegistrar { 
  2.     @Override 
  3.     public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { 
  4.         //創(chuàng)建一個(gè)bean定義對(duì)象 
  5.         RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Dog.class); 
  6.         //把bean定義對(duì)象導(dǎo)入到容器中 
  7.         registry.registerBeanDefinition("dog",rootBeanDefinition); 
  8.     } 
  9. }  
  10. @Configuration 
  11. @Import(value = {Person.class, Car.class, CustomImportSelector.class, DogBeanDefinitionRegister.class}) 
  12. public class MainConfig { 

通過(guò)實(shí)現(xiàn)FacotryBean接口來(lái)實(shí)現(xiàn)注冊(cè) 組件

  1. public class CarFactoryBean implements FactoryBean<Car> { 
  2.     @Override 
  3.     public Car getObject() throws Exception { 
  4.      return new Car(); 
  5.     }  
  6.     @Override 
  7.     public Class<?> getObjectType() { 
  8.      return Car.class; 
  9.     }  
  10.  
  11.     @Override 
  12.     public boolean isSingleton() { 
  13.      return true
  14.     } 

Bean的初始化與銷(xiāo)毀

指定bean的初始化方法和bean的銷(xiāo)毀方法

由容器管理Bean的生命周期,我們可以通過(guò)自己指定bean的初始化方法和bean的銷(xiāo)毀方法

  1. @Configuration 
  2. public class MainConfig { 
  3.     //指定了bean的生命周期的初始化方法和銷(xiāo)毀方法.@Bean(initMethod = "init",destroyMethod = "destroy"
  4.     public Car car() { 
  5.      return new Car(); 
  6.     } 

針對(duì)單實(shí)例bean的話,容器啟動(dòng)的時(shí)候,bean的對(duì)象就創(chuàng)建了,而且容器銷(xiāo)毀的時(shí)候,也會(huì)調(diào)用Bean的銷(xiāo)毀方法

針對(duì)多實(shí)例bean的話,容器啟動(dòng)的時(shí)候,bean是不會(huì)被創(chuàng)建的而是在獲取bean的時(shí)候被創(chuàng)建,而且bean的銷(xiāo)毀不受IOC容器的管理

通過(guò) InitializingBean和DisposableBean實(shí)現(xiàn)

通過(guò) InitializingBean和DisposableBean個(gè)接口實(shí)現(xiàn)bean的初始化以及銷(xiāo)毀方法

  1. @Component 
  2. public class Person implements InitializingBean,DisposableBean { 
  3.     public Person() { 
  4.      System.out.println("Person的構(gòu)造方法"); 
  5.     }  
  6.     @Override 
  7.     public void destroy() throws Exception { 
  8.      System.out.println("DisposableBean的destroy()方法 "); 
  9.     }  
  10.     @Override 
  11.     public void afterPropertiesSet() throws Exception { 
  12.      System.out.println("InitializingBean的 afterPropertiesSet方法"); 
  13.     } 

通過(guò)JSR250規(guī)范

通過(guò)JSR250規(guī)范 提供的注解@PostConstruct 和@ProDestory標(biāo)注的方法

  1. @Component 
  2. public class Book { 
  3.     public Book() { 
  4.      System.out.println("book 的構(gòu)造方法"); 
  5.     }  
  6.     @PostConstruct 
  7.     public void init() { 
  8.      System.out.println("book 的PostConstruct標(biāo)志的方法"); 
  9.     }  
  10.     @PreDestroy 
  11.     public void destory() { 
  12.      System.out.println("book 的PreDestory標(biāo)注的方法"); 
  13.     } 

通過(guò)BeanPostProcessor實(shí)現(xiàn)

通過(guò)Spring的BeanPostProcessor的 bean的后置處理器會(huì)攔截所有bean創(chuàng)建過(guò)程

  • postProcessBeforeInitialization 在init方法之前調(diào)用
  • postProcessAfterInitialization 在init方法之后調(diào)用
  1. @Component 
  2. public class CustomBeanPostProcessor implements BeanPostProcessor { 
  3.     @Override 
  4.     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 
  5.      System.out.println("CustomBeanPostProcessor...postProcessBeforeInitialization:"+beanName); 
  6.      return bean; 
  7.     }  
  8.     @Override 
  9.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 
  10.         System.out.println("CustomBeanPostProcessor...postProcessAfterInitialization:"+beanName); 
  11.         return bean; 
  12.     } 
  13. }  

BeanPostProcessor的執(zhí)行時(shí)機(jī)

  1. populateBean(beanName, mbd, instanceWrapper) 
  2. initializeBean{ 
  3.     applyBeanPostProcessorsBeforeInitialization() 
  4.     invokeInitMethods{ 
  5.     isInitializingBean.afterPropertiesSet() 
  6.     自定義的init方法 
  7. applyBeanPostProcessorsAfterInitialization()方法 

通過(guò)@Value +@PropertySource來(lái)給組件賦值

  1. public class Person { 
  2.     //通過(guò)普通的方式 
  3.     @Value("獨(dú)孤"
  4.     private String firstName; 
  5.     //spel方式來(lái)賦值 
  6.     @Value("#{28-8}"
  7.     private Integer age; 
  8.     通過(guò)讀取外部配置文件的值 
  9.     @Value("${person.lastName}"
  10.     private String lastName; 
  11. }  
  12. @Configuration 
  13. @PropertySource(value = {"classpath:person.properties"}) //指定外部文件的位置 
  14. public class MainConfig { 
  15.     @Bean 
  16.     public Person person() { 
  17.         return new Person(); 
  18.     } 

自動(dòng)裝配

@AutoWired的使用

自動(dòng)注入

  1. @Repository 
  2. public class CustomDao { 
  3. }  
  4. @Service 
  5. public class CustomService { 
  6.     @Autowired 
  7.     private CustomDao customDao; 
  8. } 

結(jié)論: (1)自動(dòng)裝配首先時(shí)按照類(lèi)型進(jìn)行裝配,若在IOC容器中發(fā)現(xiàn)了多個(gè)相同類(lèi)型的組件,那么就按照 屬性名稱(chēng)來(lái)進(jìn)行裝配

  1. @Autowired 
  2. private CustomDao customDao; 

比如,我容器中有二個(gè)CustomDao類(lèi)型的組件 一個(gè)叫CustomDao 一個(gè)叫CustomDao2那么我們通過(guò)@AutoWired 來(lái)修飾的屬性名稱(chēng)時(shí)CustomDao,那么拿就加載容器的CustomDao組件,若屬性名稱(chēng)為tulignDao2 那么他就加載的時(shí)CustomDao2組件

(2)假設(shè)我們需要指定特定的組件來(lái)進(jìn)行裝配,我們可以通過(guò)使用@Qualifier("CustomDao")來(lái)指定裝配的組件 或者在配置類(lèi)上的@Bean加上@Primary注解

  1. @Autowired 
  2. @Qualifier("CustomDao"
  3. private CustomDao customDao2 

(3)假設(shè)我們?nèi)萜髦屑礇](méi)有CustomDao 和CustomDao2,那么在裝配的時(shí)候就會(huì)拋出異常

  1. No qualifying bean of type 'com.binghhe.spring.dao.CustomDao' available 

若我們想不拋異常 ,我們需要指定 required為false的時(shí)候可以了

  1. @Autowired(required = false
  2. @Qualifier("customDao"
  3. private CustomDao CustomDao2; 

(4)@Resource(JSR250規(guī)范) 功能和@AutoWired的功能差不多一樣,但是不支持@Primary 和@Qualifier的支持

(5)@InJect(JSR330規(guī)范) 需要導(dǎo)入jar包依賴(lài),功能和支持@Primary功能 ,但是沒(méi)有Require=false的功能

  1. <dependency> 
  2.     <groupId>javax.inject</groupId> 
  3.     <artifactId>javax.inject</artifactId> 
  4.     <version>1</version> 
  5. </dependency> 

(6)使用@Autowired 可以標(biāo)注在方法上

  • 標(biāo)注在set方法上
  1. //@Autowired 
  2. public void setCustomLog(CustomLog customLog) { 
  3.  this.customLog = customLog; 
  • 標(biāo)注在構(gòu)造方法上
  1. @Autowired 
  2. public CustomAspect(CustomLog customLog) { 
  3.  this.customLog = customLog; 

標(biāo)注在配置類(lèi)上的入?yún)⒅?可以不寫(xiě))

  1. @Bean 
  2. public CustomAspect CustomAspect(@Autowired CustomLog customLog) { 
  3.     CustomAspect customAspect = new CustomAspect(customLog); 
  4.     return ustomAspect; 

XXXAwarce接口

我們自己的組件 需要使用spring ioc的底層組件的時(shí)候,比如 ApplicationContext等我們可以通過(guò)實(shí)現(xiàn)XXXAware接口來(lái)實(shí)現(xiàn)

  1. @Component 
  2. public class CustomCompent implements ApplicationContextAware,BeanNameAware { 
  3.     private ApplicationContext applicationContext; 
  4.     @Override 
  5.     public void setBeanName(String name) { 
  6.      System.out.println("current bean name is :【"+name+"】"); 
  7.     }  
  8.     @Override 
  9.     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 
  10.      this.applicationContext = applicationContext; 
  11.     } 

@Profile注解

通過(guò)@Profile注解 來(lái)根據(jù)環(huán)境來(lái)激活標(biāo)識(shí)不同的Bean

@Profile標(biāo)識(shí)在類(lèi)上,那么只有當(dāng)前環(huán)境匹配,整個(gè)配置類(lèi)才會(huì)生效

@Profile標(biāo)識(shí)在Bean上 ,那么只有當(dāng)前環(huán)境的Bean才會(huì)被激活

沒(méi)有標(biāo)志為@Profile的bean 不管在什么環(huán)境都可以被激活

  1. @Configuration 
  2. @PropertySource(value = {"classpath:ds.properties"}) 
  3. public class MainConfig implements EmbeddedValueResolverAware { 
  4.     @Value("${ds.username}"
  5.     private String userName; 
  6.     @Value("${ds.password}"
  7.     private String password
  8.     private String jdbcUrl; 
  9.     private String classDriver; 
  10.     @Override 
  11.     public void setEmbeddedValueResolver(StringValueResolver resolver) { 
  12.         this.jdbcUrl = resolver.resolveStringValue("${ds.jdbcUrl}"); 
  13.         this.classDriver = resolver.resolveStringValue("${ds.classDriver}"); 
  14.     }  
  15.     @Bean 
  16.     @Profile(value = "test"
  17.     public DataSource testDs() { 
  18.      return buliderDataSource(new DruidDataSource()); 
  19.     } 
  20.     @Bean 
  21.     @Profile(value = "dev"
  22.     public DataSource devDs() { 
  23.      return buliderDataSource(new DruidDataSource()); 
  24.     }  
  25.     @Bean 
  26.     @Profile(value = "prod"
  27.     public DataSource prodDs() { 
  28.      return buliderDataSource(new DruidDataSource()); 
  29.     }  
  30.     private DataSource buliderDataSource(DruidDataSource dataSource) { 
  31.         dataSource.setUsername(userName); 
  32.         dataSource.setPassword(password); 
  33.         dataSource.setDriverClassName(classDriver); 
  34.         dataSource.setUrl(jdbcUrl); 
  35.      return dataSource; 
  36.     } 

激活切換環(huán)境的方法

(1)運(yùn)行時(shí)jvm參數(shù)來(lái)切換

  1. -Dspring.profiles.active=test|dev|prod   

(2)通過(guò)代碼的方式來(lái)激活

  1. public static void main(String[] args) { 
  2.     AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); 
  3.     ctx.getEnvironment().setActiveProfiles("test","dev"); 
  4.     ctx.register(MainConfig.class); 
  5.     ctx.refresh(); 
  6.     printBeanName(ctx); 

本文轉(zhuǎn)載自微信公眾號(hào)「冰河技術(shù)」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系冰河技術(shù)公眾號(hào)。

 

責(zé)任編輯:武曉燕 來(lái)源: 冰河技術(shù)
相關(guān)推薦

2022-03-03 07:34:31

注解容器作用域

2017-12-22 09:59:43

2024-03-04 07:41:18

SpringAOPOOP?

2022-06-28 14:57:09

FormatterSpring

2022-05-05 10:40:36

Spring權(quán)限對(duì)象

2022-01-26 00:05:00

接口Spring管理器

2024-11-14 14:53:04

2021-11-17 08:11:35

MySQL

2023-11-09 11:56:28

MySQL死鎖

2021-08-31 07:54:24

SQLDblink查詢(xún)

2024-04-26 00:00:00

Rust檢查器代碼

2020-07-02 07:44:27

Spring教程異步

2023-04-28 08:43:46

2021-06-04 08:48:46

Spring ClouMaven Centr版本

2024-10-23 08:13:30

Spring響應(yīng)式編程

2016-01-05 10:35:04

JavaSpringJavaConfig

2021-04-13 20:24:57

Spring Boot注解spring

2023-07-28 09:54:14

SQL數(shù)據(jù)Excel

2022-05-11 09:01:54

Swift類(lèi)型系統(tǒng)幻象類(lèi)型

2021-10-30 19:56:10

Flutter按鈕 Buttons
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)