目錄html
@Configuration
聲明一個類爲IOC容器 @Bean
定義一個Beanpackage com.itcloud.annotation; import com.itcloud.pojo.Student; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class CommonConfig { @Bean public Student student(){ Student student = new Student(); student.setId(10l); student.setName("configuration"); return student; } }
測試java
package com.itcloud.pojo.anntation; import com.itcloud.annotation.CommonConfig; import com.itcloud.pojo.Student; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class AnnotationTest { ApplicationContext context = new AnnotationConfigApplicationContext(CommonConfig.class); @Test public void testAnnotation(){ Student stu = context.getBean(Student.class); } }
註解@ComponmentScan
使用詳解,該註解做用在類上面spring
@ComponentScan(value = "com.itcloud",useDefaultFilters = false,includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = { Component.class, Service.class, Repository.class }) },excludeFilters = { @ComponentScan.Filter(type=FilterType.ANNOTATION,classes = { Controller.class }) })
bean的做用域,@Scope
定義在方法上面shell
/** * 取值:singleton:默認值,單實例,容器加載的時候進行bean的建立 * prototype:容許建立多個對象,使用的時候進行隊形的建立 */ @Scope(value = "")
bean的懶加載,@Lazy
放在方法上面,在沒有這個註解的時候,bean會在容器啓動的時候進行加載,可是這個註解使用以後,當使用到這個bean的時候纔會進行性bean的加載。數據庫
@Conditional
該註解能夠根據條件進行注入操做,做用類或者方法上面數組
自定義判斷條件:此判斷條件主要的做用是判斷容器中是否存在student
bean,若是存在則注入teacher,不然不注入;app
package com.itcloud.annotation.conditional; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class MyConditional implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { BeanDefinitionRegistry registry = context.getRegistry(); boolean student = registry.containsBeanDefinition("student"); if(student){ return true; } return false; } }
@Bean("teacher") @Conditional({MyConditional.class}) public Teacher teacher(){ Teacher t = new Teacher(); t.setId(10l); t.setName("李老師"); return t; }
具體用法:按照註解的意思咱們能夠導入一個ioc
容器,ImportSelector
或者ImportBeanDefinitionRegistrar
的子類,再或者是一個普通的組件類,即被@Component
相關注解修飾的類,那麼普通的類能夠嗎?jvm
/** * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar} * or regular component classes to import. */
//在這以前咱們自定義了一個Color類ide
@Configuration @Import({Color.class}) public class CommonConfig {...}
通過測試普通類也是能夠導入的,可是普通類的bean默認的value是全類名:com.itcloud.annotation.vo.Color
post
ImportSelector測試
自定義一個MyImportSelector.java類實現ImportSelector
接口,把須要導入的類經過字符串數組的形式進行返回,必定要是全類名
參數AnnotationMetadata
能夠獲取IOC容器上面的註解
package com.itcloud.annotation.myimport; import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{"com.itcloud.annotation.vo.Blue","com.itcloud.annotation.vo.Red"}; } }
ImportBeanDefinitionRegistrar測試
package com.itcloud.annotation.myimport; import com.itcloud.annotation.vo.Yellow; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //這裏能夠進行bean的註冊 RootBeanDefinition beanDefinition = new RootBeanDefinition(Yellow.class); registry.registerBeanDefinition("yellow", beanDefinition); } }
在2>2.7裏面已經說過了,此處再也不贅述:點擊跳轉
bean的生命週期,在註解中的表現以下:
和xml配置文件類似;
@Bean(value = "student",initMethod = "init",destroyMethod = "destory")
1.註解:@PostConstruct
和 @PreDestory
在這裏必定要將此類注入到容器中,至於怎麼注入,就再也不贅述
package com.itcloud.annotation.vo; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @Component public class PostBean { public PostBean(){ System.out.println("構造方法執行....."); } @PostConstruct public void postConstruct(){ System.out.println("postConstruct......"); } @PreDestroy public void destroy(){ System.out.println("容器關閉以前執行的嗎......"); } }
測試結果:
<!-- 構造方法執行..... postConstruct...... ## 容器關閉以前執行以下 容器關閉以前執行的嗎...... -->
2.兩個接口 InitializingBean
DisposableBean
package com.itcloud.annotation.vo; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; public class PostProcessorBean implements InitializingBean, DisposableBean { public PostProcessorBean(){ System.out.println("PostProcessorBean.....構造方法執行"); } @Override public void destroy() throws Exception { System.out.println("PostProcessorBean.......destroy()"); } //屬性設置完成以後執行,構造方法以後調用 @Override public void afterPropertiesSet() throws Exception { System.out.println("PostProcessorBean.......afterPropertiesSet()"); } }
3.BeanPostProcessor
原理解析
在前面後置處理器中咱們已經瞭解了,經過實現接口BeanPostProcessor
能夠進行後置處理,在這裏咱們將要對後置處理原理進行簡單的介紹
定義一個後置處理器
這個處理器會在全部bean建立的時候,構造方法以後執行,全部初始化方法以前執行,而方法postProcessAfterInitialization
會在初始化以後調用,不須要容器關閉
package com.itcloud.processor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; @Component public class MyProcessor implements BeanPostProcessor{ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("Before*****beanName = " + beanName +"-----bean = " + bean); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("After*****beanName = " + beanName +"----bean = " + bean); return bean; } }
package com.itcloud.processor; import com.itcloud.annotation.vo.Color; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.stereotype.Component; @Configuration @ComponentScan(useDefaultFilters = false, includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = { Component.class }) }) public class ProcessorConfig { @Bean public Color color(){ return new Color(); } }
源碼解析:
1.@Value的使用
package com.itcloud.annotation.vo; import org.springframework.beans.factory.annotation.Value; public class Color { //直接賦值 @Value("red") private String type; //EL表達式 @Value("#{100.30-13.43}") private Double length; //引用外部屬性文件 @Value("${value.username}") private String username; @Value("${value.password}") private String password; }
在配置類上面必定要引用外部文件,經過註解@PropertySource
package com.itcloud.processor; import com.itcloud.annotation.vo.Color; import org.springframework.context.annotation.*; import org.springframework.stereotype.Component; @Configuration @ComponentScan(useDefaultFilters = false, includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = { Component.class }) }) @PropertySource("classpath:/properties/value.properties") public class ProcessorConfig { @Bean public Color color(){ return new Color(); } }
經過環境變量來獲取屬性的值
Environment environment = context.getEnvironment(); String property = environment.getProperty("value.username");
2.自動裝配使用的註解
2.一、spring註解:@Autowired前面咱們已經說過,這個註解能夠配合@Qualifier使用,明確調用使用特定的Bean
@Autowired也能夠配置@Primary註解使用,當類型相同的使用,會優先選擇@Primary註解標識的 bean
2.2.非spring註解:@Resource按照名稱注入,@Inject,@Autowired用法相似,須要引入jar:
<dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency>
若是一個類想要使用spring底層的組件,能夠實現一些接口xxxAware
,這個接口都是org.springframework.beans.factory.Aware
接口的子類
1.xxxAware
方法的使用
package com.itcloud.annotation.vo; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanNameAware; import org.springframework.context.*; import org.springframework.core.env.Environment; import org.springframework.util.StringValueResolver; public class Color implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware { private ApplicationContext context; public void userContext(){ Environment environment = this.context.getEnvironment(); String property = environment.getProperty("value.url"); System.out.println(property); } //獲取applicationContext對象 @Override public void setApplicationContext(ApplicationContext context) throws BeansException { this.context = context; } //獲取當前bean的name @Override public void setBeanName(String name) { System.out.println("name===" + name); } //進行字符串的解析 @Override public void setEmbeddedValueResolver(StringValueResolver resolver) { String result = resolver.resolveStringValue("數據庫的名稱:${value.username}, el表達式解析:#{10-3*3}"); System.out.println(result); } }
此註解既可使用在bean上,也能夠定義在一個IOC容器上面,激活的方式:
1.類激活
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.getEnvironment().setActiveProfiles("development"); ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class); ctx.refresh();
2.jvm參數激活:
-Dspring.profiles.active="profile1,profile2"