@Configuration用於定義配置類,可替換XML配置文件,被註解的類內部包含有一個或者多個被@Bean註解的方法,這些方法將會被AnnotationConfigApplicationContext或者AnnotationConfigWebApplicationContext類進行掃描,並用於構建Bean定義,初始化Spring容器。html
@Configuration public class MySpringConfig { @Bean public UserEntity userEntity() { return new UserEntity("xuyu", 21); } }
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MySpringConfig.class);
1.一、@Configuration配置spring並啓動spring容器
1.二、@Configuration啓動容器+@Bean註冊Bean
1.三、@Configuration啓動容器+@Component註冊Bean
1.四、使用 AnnotationConfigApplicationContext 註冊 AppContext 類的spring
2.一、在@configuration中引入其它註解配置
2.二、@configuration嵌套源碼分析
@Configuration標註在類上,至關於把該類做爲spring的xml配置文件中的
<beans>
,做用爲:配置spring容器(應用上下文)測試
@Configuration public class TestConfiguration { public TestConfiguration() { System.out.println("TestConfiguration容器啓動初始化。。。"); } }
至關於:this
<?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" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd" default-lazy-init="false"> </beans>
主方法進行測試:url
public class TestMain { public static void main(String[] args) { // @Configuration註解的spring容器加載方式,用AnnotationConfigApplicationContext替換ClassPathXmlApplicationContext ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class); // 若是加載spring-context.xml文件: // ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml"); } }
從運行主方法結果能夠看出,spring容器已經啓動了:spa
@Bean標註在方法上(返回某個實例的方法),等價於spring的xml配置文件中的<bean>
,做用爲:註冊bean對象.net
bean類:prototype
public class TestBean { private String username; private String url; private String password; public void sayHello() { System.out.println("TestBean sayHello..."); } public String toString() { return "username:" + this.username + ",url:" + this.url + ",password:" + this.password; } public void start() { System.out.println("TestBean 初始化。。。"); } public void cleanUp() { System.out.println("TestBean 銷燬。。。"); } }
配置類:code
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; @Configuration public class TestConfiguration { public TestConfiguration() { System.out.println("TestConfiguration容器啓動初始化。。。"); } // @Bean註解註冊bean,同時能夠指定初始化和銷燬方法 // @Bean(name="testBean",initMethod="start",destroyMethod="cleanUp") @Bean @Scope("prototype") public TestBean testBean() { return new TestBean(); } }
主方法測試類:
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class TestMain { public static void main(String[] args) { // @Configuration註解的spring容器加載方式,用AnnotationConfigApplicationContext替換ClassPathXmlApplicationContext ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class); // 若是加載spring-context.xml文件: // ApplicationContext context = new // ClassPathXmlApplicationContext("spring-context.xml"); //獲取bean TestBean tb = (TestBean) context.getBean("testBean"); tb.sayHello(); } }
結果:
注:
(1)、@Bean註解在返回實例的方法上,若是未經過@Bean指定bean的名稱,則默認與標註的方法名相同;
(2)、@Bean註解默認做用域爲單例singleton做用域,可經過@Scope(「prototype」)設置爲原型做用域;
(3)、既然@Bean的做用是註冊bean對象,那麼徹底能夠使用@Component、@Controller、@Service、@Ripository等註解註冊bean,固然須要配置@ComponentScan註解進行自動掃描。
能夠使用基於 Java 的配置來管理 bean 的生命週期。
@Bean
支持兩種屬性,即initMethod
和destroyMethod
,這些屬性可用於定義生命週期方法。在實例化 bean 或即將銷燬它時,容器即可調用生命週期方法。生命週期方法也稱爲回調方法,由於它將由容器調用。使用
@Bean
註釋註冊的 bean 也支持 JSR-250 規定的標準@PostConstruct
和@PreDestroy
註釋。若是您正在使用 XML 方法來定義 bean,那麼就應該使用 bean 元素來定義生命週期回調方法。如下代碼顯示了在 XML 配置中一般使用 bean 元素定義回調的方法。
package com.mayikt.v1.entity; public class TestBean { public void sayHello() { System.out.println("TestBean sayHello..."); } public void start() { System.out.println("TestBean 初始化。。。"); } public void cleanUp() { System.out.println("TestBean 銷燬。。。"); } }
@Configuration @ComponentScan(basePackages = "com.mayikt.v1.entity") public class TestConfiguration { public TestConfiguration() { System.out.println("TestConfiguration容器啓動初始化。。。"); } //@Bean註解註冊bean,同時能夠指定初始化和銷燬方法 @Bean(name="testBean",initMethod="start",destroyMethod="cleanUp") @Scope("prototype") public TestBean testBean() { return new TestBean(); } }
public class TestMain { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class); TestBean tb = (TestBean) context.getBean("testBean"); tb.sayHello(); System.out.println(tb); TestBean tb2 = (TestBean) context.getBean("testBean"); tb2.sayHello(); System.out.println(tb2); } }
分析:
結果中的1:代表initMethod生效
結果中的2:代表@Scope("prototype")生效
//添加註冊bean的註解 @Component public class TestBean { private String username; private String url; private String password; public void sayHello() { System.out.println("TestBean sayHello..."); } public String toString() { return "username:" + this.username + ",url:" + this.url + ",password:" + this.password; } public void start() { System.out.println("TestBean 初始化。。。"); } public void cleanUp() { System.out.println("TestBean 銷燬。。。"); } }
@Configuration //添加自動掃描註解,basePackages爲TestBean包路徑 @ComponentScan(basePackages = "com.mayikt.v1.entity") public class TestConfiguration { public TestConfiguration() { System.out.println("TestConfiguration容器啓動初始化。。。"); } }
public class TestMain { public static void main(String[] args) { // @Configuration註解的spring容器加載方式,用AnnotationConfigApplicationContext替換ClassPathXmlApplicationContext ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class); // 若是加載spring-context.xml文件: // ApplicationContext context = new // ClassPathXmlApplicationContext("spring-context.xml"); //獲取bean TestBean tb = (TestBean) context.getBean("testBean"); tb.sayHello(); } }
AnnotationConfigApplicationContext
的register
方法傳入配置類來註冊配置類
public class TestMain { public static void main(String[] args) { // @Configuration註解的spring容器加載方式,用AnnotationConfigApplicationContext替換ClassPathXmlApplicationContext ApplicationContext context = new AnnotationConfigApplicationContext(); ((AnnotationConfigApplicationContext) context).register(TestConfiguration.class); String[] beanDefinitionNames = context.getBeanDefinitionNames(); for (int i = 0; i < beanDefinitionNames.length; i++) { System.out.println(beanDefinitionNames[i]); } } }
@Configuation等價於<Beans></Beans>
@Bean等價於<Bean></Bean>
@ComponentScan等價於<context:component-scan base-package="com.xxx"/>
@Configuration @Import(TestConfiguration.class) public class WebConfig { }
@Configuration @ComponentScan(basePackages = "com.mayikt.v1.entity") public class TestConfiguration { public TestConfiguration() { System.out.println("TestConfiguration容器啓動初始化。。。"); } //@Bean註解註冊bean,同時能夠指定初始化和銷燬方法 @Bean(name="testBean2",initMethod="start",destroyMethod="cleanUp") @Scope("prototype") public TestBean2 testBean2() { return new TestBean2(); } }
public class TestMain2 { public static void main(String[] args) { // @Configuration註解的spring容器加載方式,用AnnotationConfigApplicationContext替換ClassPathXmlApplicationContext ApplicationContext context = new AnnotationConfigApplicationContext(WebConfig.class); // 獲取bean TestBean2 tb2 = (TestBean2) context.getBean("testBean2"); tb2.sayHello(); TestBean tb = (TestBean) context.getBean("testBean"); tb.sayHello(); } }
結果:
@Configuration public class MySpringConfig { @Configuration static class entity{ @Bean UserEntity userEntity(){ return new UserEntity("mayikt", 21); } } /*@Bean public UserEntity userEntity() { return new UserEntity("xuyu", 21); }*/ }
public class V2TestSpring { private static AnnotationConfigApplicationContext annotationConfigApplicationContext; public static void main(String[] args) { annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MySpringConfig.class); System.out.println("啓動配置加載完畢..."); UserEntity userEntity = annotationConfigApplicationContext.getBean("userEntity", UserEntity.class); String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames(); for (int i = 0; i < beanDefinitionNames.length; i++) { System.out.println(beanDefinitionNames[i]); } } }
結果
配合@Configuration使用,包括 @EnableAsync, @EnableScheduling, @EnableTransactionManagement, @EnableAspectJAutoProxy, @EnableWebMvc。
@EnableAspectJAutoProxy---《spring AOP 之:@Aspect註解》
@EnableScheduling--《Spring 3.1新特性之二:@Enable*註解的源碼,spring源碼分析之定時任務Scheduled註解》
一、@PropertySource + Environment,經過@PropertySource註解將properties配置文件中的值存儲到Spring的 Environment中,Environment接口提供方法去讀取配置文件中的值,參數是properties文件中定義的key值。
二、@PropertySource(PropertySourcesPlaceholderConfigurer)+@Value
答案:默認狀況下是非懶加載的。
- Lazy表示爲懶加載,當真正須要引用獲取的時候纔會被加載
- True 表示爲非懶加載 false表示爲在IOC容器加載的時候被建立
@Service @Lazy(true) public class UserService { public UserService() { System.out.println("UserService無參數構造被加載..."); } }