Spring基于Java的配置
以下内容引用自http://wiki.jikexueyuan.com/project/spring/java-based-configuration.html:
基于Java的配置选项,可以使你在不用配置XML的情况下编写大多数的Spring配置。
@Configuration和@Bean注解
带有@Configuration的注解类表示这个类可以使用Spring IoC容器作为bean定义的来源。@Bean注解告诉Spring,一个带有@Bean的注解方法将返回一个对象,该对象应该被注册为在Spring应用程序上下文中的bean。最简单可行的@Configuration类如下所示:
@Configuration public class HelloWorldConfig { @Bean public HelloWorld helloWorld(){ return new HelloWorld(); } }
对应XML配置如下:
<beans> <bean id="helloWorld" class="com.jsoft.testspring.testjavaconfiguration.HelloWorld" /> </beans>
在这里,带有@Bean注解的方法名称作为bean的ID,它创建并返回实际的bean。你的配置类可以声明多个@Bean。一旦定义了配置类,你就可以使用AnnotationConfigApplicationContext来加载并把他们提供给Spring容器,如下所示:
public static void main( String[] args ) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(HelloWorldConfig.class); HelloWorld helloWorld = applicationContext.getBean(HelloWorld.class); helloWorld.setMessage("Hello World!"); helloWorld.getMessage(); }
当然,你可以加载各种配置类,如下所示:
public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(AppConfig.class, OtherConfig.class); ctx.register(AdditionalConfig.class); ctx.refresh(); MyService myService = ctx.getBean(MyService.class); myService.doStuff(); }
例子:
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jsoft.testspring</groupId> <artifactId>testjavaconfiguration</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>testjavaconfiguration</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- Spring Core --> <!-- http://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.1.4.RELEASE</version> </dependency> <!-- Spring Context --> <!-- http://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.4.RELEASE</version> </dependency> </dependencies> </project>
HelloWorld.java:
package com.jsoft.testspring.testjavaconfiguration; public class HelloWorld { private String message; public void setMessage(String message){ this.message = message; } public void getMessage(){ System.out.println(this.message); } }
HelloWorldConfig.java:
package com.jsoft.testspring.testjavaconfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class HelloWorldConfig { @Bean public HelloWorld helloWorld(){ return new HelloWorld(); } }
App.java:
package com.jsoft.testspring.testjavaconfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * Hello world! * */ public class App { public static void main( String[] args ) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(HelloWorldConfig.class); HelloWorld helloWorld = applicationContext.getBean(HelloWorld.class); helloWorld.setMessage("Hello World!"); helloWorld.getMessage(); } }
测试结果:
测试工程:https://github.com/easonjim/5_java_example/tree/master/springtest/test13/testjavaconfiguration
Bean的依赖性注入
当Beans依赖对方时,表达这种依赖性非常简单,只要有一个bean方法调用另一个,如下所示:
@Configuration public class HelloWorldConfig { @Bean public HelloWorld helloWorld(){ return new HelloWorld(message()); } @Bean public String message(){ return new String("Hello World"); } }
可以看出,有依赖性时直接在类中调用新建的方法即可。
例子:
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jsoft.testspring</groupId> <artifactId>testjavaconfiguration</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>testjavaconfiguration</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- Spring Core --> <!-- http://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.1.4.RELEASE</version> </dependency> <!-- Spring Context --> <!-- http://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.4.RELEASE</version> </dependency> </dependencies> </project>
HelloWorld.java:
package com.jsoft.testspring.testjavaconfiguration; public class HelloWorld { private String message; public HelloWorld(String message){ this.message = message; } public void getMessage(){ System.out.println(this.message); } }
HelloWorldConfig.java:
package com.jsoft.testspring.testjavaconfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class HelloWorldConfig { @Bean public HelloWorld helloWorld(){ return new HelloWorld(message()); } @Bean public String message(){ return new String("Hello World"); } }
App.java:
package com.jsoft.testspring.testjavaconfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * Hello world! * */ public class App { public static void main( String[] args ) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(HelloWorldConfig.class); HelloWorld helloWorld = applicationContext.getBean(HelloWorld.class); helloWorld.getMessage(); } }
测试结果:
测试工程:https://github.com/easonjim/5_java_example/tree/master/springtest/test13/testjavaconfiguration1
@Import注释
@import注解允许从另一个配置类中加载Bean定义。如下所示:
@Configuration public class ConfigA { @Bean public A a() { return new A(); } }
@Configuration @Import(ConfigA.class) public class ConfigB { @Bean public B b() { return new B(); } }
现在,当实例化上下文时,不需要同时指定ConfigA.class和ConfigB.class,只要ConfigB类需要提供,如下所示:
public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class); A a = ctx.getBean(A.class); B b = ctx.getBean(B.class); }
例子:
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jsoft.testspring</groupId> <artifactId>testjavaconfiguration</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>testjavaconfiguration</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- Spring Core --> <!-- http://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.1.4.RELEASE</version> </dependency> <!-- Spring Context --> <!-- http://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.4.RELEASE</version> </dependency> </dependencies> </project>
HelloWorld.java:
package com.jsoft.testspring.testjavaconfiguration; public class HelloWorld { private String message; public HelloWorld(String message){ this.message = message; } public void getMessage(){ System.out.println(this.message); } }
HelloWorldConfig.java:
package com.jsoft.testspring.testjavaconfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class HelloWorldConfig { @Bean public HelloWorld helloWorld(){ return new HelloWorld(message()); } @Bean public String message(){ return new String("Hello World"); } }
HelloWorldConfigB.java:
package com.jsoft.testspring.testjavaconfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration @Import(HelloWorldConfig.class) public class HelloWorldConfigB { @Bean public String messageB(){ return new String("Hello B"); } }
App.java:
package com.jsoft.testspring.testjavaconfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * Hello world! * */ public class App { public static void main( String[] args ) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(HelloWorldConfigB.class); HelloWorld helloWorld = applicationContext.getBean(HelloWorld.class); helloWorld.getMessage(); } }
可以看出不用再次引用HelloWorldConfig.java类了。
测试结果:
测试工程:https://github.com/easonjim/5_java_example/tree/master/springtest/test13/testjavaconfiguration2
生命周期回调
@Bean注解支持指定任意的初始化和销毁回调方法,这与Spring元素中的Spring XML的init-method和destroy-method属性非常相似。如下所示:
public class Foo { public void init() { } public void cleanup() { } } @Configuration public class AppConfig { @Bean(initMethod = "init", destroyMethod = "cleanup" ) public Foo foo() { return new Foo(); } }
例子:
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jsoft.testspring</groupId> <artifactId>testjavaconfiguration</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>testjavaconfiguration</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- Spring Core --> <!-- http://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.1.4.RELEASE</version> </dependency> <!-- Spring Context --> <!-- http://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.4.RELEASE</version> </dependency> </dependencies> </project>
HelloWorld.java:
package com.jsoft.testspring.testjavaconfiguration; public class HelloWorld { private String message; public HelloWorld(String message){ this.message = message; } public void getMessage(){ System.out.println(this.message); } public void init(){ System.out.println("HelloWorld init"); } public void cleanup(){ System.out.println("HelloWorld cleanup"); } }
HelloWorldConfig.java:
package com.jsoft.testspring.testjavaconfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class HelloWorldConfig { @Bean(initMethod="init",destroyMethod="cleanup") public HelloWorld helloWorld(){ return new HelloWorld(message()); } @Bean public String message(){ return new String("Hello World"); } }
App.java:
package com.jsoft.testspring.testjavaconfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.AbstractApplicationContext; /** * Hello world! * */ public class App { public static void main( String[] args ) { AbstractApplicationContext applicationContext = new AnnotationConfigApplicationContext(HelloWorldConfig.class); HelloWorld helloWorld = applicationContext.getBean(HelloWorld.class); helloWorld.getMessage(); applicationContext.registerShutdownHook(); } }
测试结果:
测试工程:https://github.com/easonjim/5_java_example/tree/master/springtest/test13/testjavaconfiguration3
指定Bean的作用域范围
默认范围是单实例,但是你可以重写带有@Scope注解的方法,如下所示:
@Configuration public class AppConfig { @Bean @Scope("prototype") public Foo foo() { return new Foo(); } }
例子:
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jsoft.testspring</groupId> <artifactId>testjavaconfiguration</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>testjavaconfiguration</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- Spring Core --> <!-- http://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.1.4.RELEASE</version> </dependency> <!-- Spring Context --> <!-- http://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.4.RELEASE</version> </dependency> </dependencies> </project>
HelloWorld.java:
package com.jsoft.testspring.testjavaconfiguration; public class HelloWorld { private String message; public void setMessage(String message){ this.message = message; } public void getMessage(){ System.out.println(this.message); } }
HelloWorldConfig.java:
package com.jsoft.testspring.testjavaconfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; @Configuration public class HelloWorldConfig { @Bean @Scope("prototype") public HelloWorld helloWorld(){ return new HelloWorld(); } }
@Scope的值和xml中配置的保持一致。
App.java:
package com.jsoft.testspring.testjavaconfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * Hello world! * */ public class App { public static void main( String[] args ) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(HelloWorldConfig.class); HelloWorld helloWorld = applicationContext.getBean(HelloWorld.class); helloWorld.setMessage("Hello World 1!"); helloWorld.getMessage(); HelloWorld helloWorld2 = applicationContext.getBean(HelloWorld.class); helloWorld2.getMessage(); } }
测试结果:
测试工程:https://github.com/easonjim/5_java_example/tree/master/springtest/test13/testjavaconfiguration4
更多Java配置的官方例子参考:https://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch02s02.html