溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

IOC容器注解的相關(guān)知識(shí)點(diǎn)有哪些

發(fā)布時(shí)間:2021-10-28 15:39:47 來(lái)源:億速云 閱讀:114 作者:iii 欄目:web開(kāi)發(fā)

這篇文章主要講解了“IOC容器注解的相關(guān)知識(shí)點(diǎn)有哪些”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“IOC容器注解的相關(guān)知識(shí)點(diǎn)有哪些”吧!

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

1.xml配置

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

<?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/sp  <bean id="person" class="com.binghe.spring.Person"></bean> </beans>

2.類(lèi)配置

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

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

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

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

@CompentScan注解

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

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

excludeFilters 屬性

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

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

includeFilters屬性

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

@Configuration @ComponentScan(basePackages = {"com.binghe.spring"},includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class, PersonService.class}) },useDefaultFilters = false) 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

public enum FilterType {     //注解形式 比如@Controller @Service @Repository @Compent     ANNOTATION,     //指定的類(lèi)型     ASSIGNABLE_TYPE,     //aspectJ形式的     ASPECTJ,     //正則表達(dá)式的     REGEX,     //自定義的     CUSTOM }

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

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

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

不指定@Scope

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

@Bean public Person person() {  return new Person(); }

@Scope為 prototype

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

@Bean @Scope(value = "prototype") public Person person() {     return new Person(); }

@Scope取值

  • singleton 單實(shí)例的(默認(rèn))

  • prototype 多實(shí)例的

  • request 同一次請(qǐng)求

  • session 同一個(gè)會(huì)話(huà)級(jí)別

懶加載

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

@Bean @Lazy public Person person() {  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接口

public class CustomCondition implements Condition { /**** @param context * @param metadata * @return */     @Override     public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {         //判斷容器中是否有CustomAspect的組件         return context.getBeanFactory().containsBean("customAspect");     }  }   public class MainConfig {     @Bean     public CustomAspect customAspect() {         return new CustomAspect();     }      @Bean     @Conditional(value = CustomCondition.class)     public CustomLog customLog() {      return new CustomLog();     } }

向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)名路徑)

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

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

public class CustomImportSelector implements ImportSelector {      @Override     public String[] selectImports(AnnotationMetadata importingClassMetadata) {      return new String[]{"com.binghe.spring"};     } }  Configuration @Import(value = {Person.class} public class MainConfig { }

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

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

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

public class CarFactoryBean implements FactoryBean<Car> {     @Override     public Car getObject() throws Exception {      return new Car();     }      @Override     public Class<?> getObjectType() {      return Car.class;     }       @Override     public boolean isSingleton() {      return true;     } }

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

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

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

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

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

針對(duì)多實(shí)例bean的話(huà),容器啟動(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)毀方法

@Component public class Person implements InitializingBean,DisposableBean {     public Person() {      System.out.println("Person的構(gòu)造方法");     }      @Override     public void destroy() throws Exception {      System.out.println("DisposableBean的destroy()方法 ");     }      @Override     public void afterPropertiesSet() throws Exception {      System.out.println("InitializingBean的 afterPropertiesSet方法");     } }

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

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

@Component public class Book {     public Book() {      System.out.println("book 的構(gòu)造方法");     }      @PostConstruct     public void init() {      System.out.println("book 的PostConstruct標(biāo)志的方法");     }      @PreDestroy     public void destory() {      System.out.println("book 的PreDestory標(biāo)注的方法");     } }

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

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

  • postProcessBeforeInitialization 在init方法之前調(diào)用

  • postProcessAfterInitialization 在init方法之后調(diào)用

@Component public class CustomBeanPostProcessor implements BeanPostProcessor {     @Override     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {      System.out.println("CustomBeanPostProcessor...postProcessBeforeInitialization:"+beanName);      return bean;     }      @Override     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {         System.out.println("CustomBeanPostProcessor...postProcessAfterInitialization:"+beanName);         return bean;     } }

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

populateBean(beanName, mbd, instanceWrapper) initializeBean{     applyBeanPostProcessorsBeforeInitialization()     invokeInitMethods{     isInitializingBean.afterPropertiesSet()     自定義的init方法 } applyBeanPostProcessorsAfterInitialization()方法 }

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

public class Person {     //通過(guò)普通的方式     @Value("獨(dú)孤")     private String firstName;     //spel方式來(lái)賦值     @Value("#{28-8}")     private Integer age;     通過(guò)讀取外部配置文件的值     @Value("${person.lastName}")     private String lastName; }  @Configuration @PropertySource(value = {"classpath:person.properties"}) //指定外部文件的位置 public class MainConfig {     @Bean     public Person person() {         return new Person();     } }

自動(dòng)裝配

@AutoWired的使用

自動(dòng)注入

@Repository public class CustomDao { }  @Service public class CustomService {     @Autowired     private CustomDao customDao; }

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

@Autowired 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注解

@Autowired @Qualifier("CustomDao") private CustomDao customDao2

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

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

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

@Autowired(required = false) @Qualifier("customDao") private CustomDao CustomDao2;

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

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

<dependency>     <groupId>javax.inject</groupId>     <artifactId>javax.inject</artifactId>     <version>1</version> </dependency>

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

  • 標(biāo)注在set方法上

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

@Autowired public CustomAspect(CustomLog customLog) {  this.customLog = customLog; }

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

@Bean public CustomAspect CustomAspect(@Autowired CustomLog customLog) {     CustomAspect customAspect = new CustomAspect(customLog);     return ustomAspect; }

XXXAwarce接口

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

@Component public class CustomCompent implements ApplicationContextAware,BeanNameAware {     private ApplicationContext applicationContext;     @Override     public void setBeanName(String name) {      System.out.println("current bean name is :【"+name+"】");     }      @Override     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {      this.applicationContext = applicationContext;     } }

@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)境都可以被激活

@Configuration @PropertySource(value = {"classpath:ds.properties"}) public class MainConfig implements EmbeddedValueResolverAware {     @Value("${ds.username}")     private String userName;     @Value("${ds.password}")     private String password;     private String jdbcUrl;     private String classDriver;     @Override     public void setEmbeddedValueResolver(StringValueResolver resolver) {         this.jdbcUrl = resolver.resolveStringValue("${ds.jdbcUrl}");         this.classDriver = resolver.resolveStringValue("${ds.classDriver}");     }      @Bean     @Profile(value = "test")     public DataSource testDs() {      return buliderDataSource(new DruidDataSource());     }     @Bean     @Profile(value = "dev")     public DataSource devDs() {      return buliderDataSource(new DruidDataSource());     }      @Bean     @Profile(value = "prod")     public DataSource prodDs() {      return buliderDataSource(new DruidDataSource());     }      private DataSource buliderDataSource(DruidDataSource dataSource) {         dataSource.setUsername(userName);         dataSource.setPassword(password);         dataSource.setDriverClassName(classDriver);         dataSource.setUrl(jdbcUrl);      return dataSource;     } }

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

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

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

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

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

感謝各位的閱讀,以上就是“IOC容器注解的相關(guān)知識(shí)點(diǎn)有哪些”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)IOC容器注解的相關(guān)知識(shí)點(diǎn)有哪些這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

ioc
AI