`

Spring(17)——使用Java类的形式配置bean

阅读更多

17 使用Java类的形式配置bean定义

除了传统的使用XML来配置底层的bean容器定义,Spring还支持使用大家熟悉的Java类的形式来进行配置。使用Java类的形式来进行配置时我们将使用一个Java类来作为配置的主体,并在类上使用@Configuration进行标注,表示其是一个配置类。然后将对应的bean定义都定义为Java配置类中的一个公用方法,并在方法上使用@Bean进行标注,表示其是一个bean定义。使用@Bean进行标注的方法对应的返回类型就是生成的bean定义对应的Class类型,对应的方法体实现就是我们用来产生对应bean定义的实例的过程,对应的方法名就是bean定义的默认beanName。下面我们先来简单的看一个对应的实现。

@Configuration
public class SpringConfig {

	@Bean
	public Hello hello() {
		return new Hello();
	}
	
}

在上面代码中我们就通过@Configuration标注了我们的类SpringConfig是一个Spring的配置类,然后在其中定义了一个使用@Bean进行标注的方法,Spring会将其作为一个bean定义添加到bean容器中,对应beanName为“hello”,然后直接new一个对应的实例作为bean定义的实例。之后我们就可以从该配置类产生的bean容器中获取对应的bean定义了,对应测试代码可以是如下这样。

@ContextConfiguration(classes={SpringConfig.class})
@RunWith(SpringJUnit4ClassRunner.class)
public class ConfigurationTest {
	
	@Autowired
	private ApplicationContext context;
	
	@Test
	public void test() {
		System.out.println(context.getBean("hello", Hello.class));
	}

}

17.1 @Bean

在使用基于Java类进行配置时,我们可以使用@Bean来标注配置类中需要定义为bean容器中一个bean定义的方法。标注后,默认会以该方法的名称作为对应bean定义的beanName,以方法的返回类型作为对应bean定义的Class类型。

@Configuration
public class SpringConfig {

	@Bean
	public Hello hello() {
		return new Hello();
	}
	
}

如上示例,我们就在基于Java类的配置中使用@Bean注解定义了一个bean定义,其相当于我们在XML配置文件中的如下定义。

<bean id="hello" class="com.app.Hello"/>

17.1.1 指定beanName

默认情况Spring会以方法名称作为对应bean定义的beanName。如果用户希望指定对应bean定义的beanName,则可以通过@Bean的name属性进行指定。

@Bean(name="hello1")
public Hello hello() {
	return new Hello();
}

我们也可以通过@Bean的name属性给bean定义指定多个名称,这个时候就可以将name属性以一个数组的形式进行指定。如下示例中我们就表示同时指定beanName为“hello”和“hello1”。

@Bean(name={"hello", "hello1"})
public Hello hello() {
	return new Hello();
}

17.1.2 指定生命周期回调方法

根据之前文章的介绍我们知道bean的生命周期回调方法可以通过三种方式进行指定,使用JSR-250标准的@PostConstruct和@PreDestroy进行标注、实现InitializationBean和DisposableBean接口和通过bean定义的init-method和destroy-method进行指定。对于前两种方式而言,使用@Bean进行配置的bean也可以像其它基于注解或基于XML配置的bean一样进行回调。对于第三种方式,我们就需要通过@Bean的initMethod和destroyMethod属性进行指定,对应属性值即表示对应的回调方法名称。

	@Bean(initMethod="init", destroyMethod="destroy")
	public Hello hello() {
		return new Hello();
	}

上述示例中我们就通过initMethod属性指定了bean hello的初始化回调方法为init(),通过destroyMethod属性指定了对应的销毁前回调方法为destroy()。其就相当于我们基于XML配置的如下形式。

<bean id="hello" class="com.app.Hello" init-method="init" destroy-method="destroy"/>

17.1.3 指定是否自动注入

在使用XML进行配置的时候,我们可以通过其autowire指定是否需要进行自动注入。对应的我们可以在@Bean上使用autowire属性来指定是否进行自动注入。可选值有Autowire.NO、Autowire.BY_NAME和Autowire.BY_TYPE。默认是Autowire.NO,即不进行自动注入。Autowire.BY_NAME表示按名称进行自动注入,Autowire.BY_TYPE表示按类型进行自动注入。

	@Bean(autowire=Autowire.BY_TYPE)
	public Hello hello() {
		return new Hello();
	}

上述示例表示按照类型对依赖的bean进行自动注入。其等同于如下XML定义。

<bean id="hello" class="com.app.Hello" autowire="byType"/>

17.1.4 指定Scope

通过@Bean进行定义的bean对应的Scope默认也是singleton的,用户如果希望更改这种默认策略,则需要在@Bean对应的方法上使用@Scope标注进行定义,具体用法与我们之前介绍的在基于注解配置bean定义时是一样的。如下表示我们定义对应的Scope为prototype。

	@Bean
	@Scope("prototype")
	public Hello hello() {
		return new Hello();
	}

如果需要被代理,可以指定proxyMode。

	@Bean
	@Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)
	public Hello hello() {
		return new Hello();
	}

17.1.5 依赖注入

对于处于同一个使用@Configuration进行标注的配置类中的bean注入,我们可以直接通过方法调用的形式来获取对应的bean实例以进行注入。如下示例中我们就通过调用world()方法获取了一个World实例,然后注入给了Hello的实例。

	@Bean
	public Hello hello() {
		Hello hello = new Hello();
		hello.setWorld(this.world());
		return hello;
	}
	
	@Bean
	public World world() {
		return new World();
	}

也可以像之前介绍的使用@Autowired或@Inject标注进行自动注入,即在对应的bean对应的Class类中进行定义。如下示例中我们就通过@Autowired定义了world需要进行自动注入。对于使用Java类进行配置的情况,Spring会自动扫描对应的注解以完成对应的bean定义。

public class Hello {
	
	@Autowired
	private World world;

}

再来看一个示例,在下面的示例中,我们调用了两次world()方法,分别获取对应的bean实例注入hello和beanA。因为Spring默认生成的bean实例是singleton类型的,为了实现这种机制,则在第一次调用world()产生了第一个实例后,Spring会将对应的对象缓存起来,待下次再调用world()方法获取实例时则直接获取缓存起来的那个实例。所以对于如下这种情况,实际上Spring也只会产生一个World实例。Spring的这种基于Java类配置的单例bean机制是通过CGLIB动态生成类来实现的,在系统启动时,Spring将通过CGLIB构建所有使用@Configuration进行标注的Class的子类,在子类调用父类对应方法产生对应的bean实例之前,会先从子类的缓存中获取,只有在取不到的情况下才会调用父类产生新的实例,产生了对应的实例后就将其缓存到对应的缓存中。另外,鉴于Spring的这种机制就要求我们对应的Java配置Class不是final型的,且存在一个无参构造方法。

@Configuration
public class SpringConfig {

	@Bean
	public Hello hello() {
		Hello hello = new Hello();
		hello.setWorld(world());
		return hello;
	}
	
	@Bean
	public World world() {
		return new World();
	}
	
	@Bean
	public BeanA beanA() {
		BeanA beanA = new BeanA();
		beanA.setWorld(world());
		return beanA;
	}
	
}

17.1.6 使用lookup-method

在之前介绍XML配置时,我们曾使用lookup-method的方式以解决单例bean引用多例bean的问题。在使用基于Java进行配置时如果我们也希望以这样的方式来解决单例bean引用多例bean的情况,则我们可以通过如下方式进行解决。打个比方我们有一个单例bean,对应类Hello,其需要引用一个多例的bean World,那么我们就可以在Hello中定义一个公用的方法以获取World实例,然后每次需要使用World实例时都通过该方法获取,如下的getWorld()方法就是这个功能。

public class Hello {
	
	public void doSomething() {
		World world = this.getWorld();
		System.out.println(world);
		//...
	}
	
	public World getWorld() {
		return null;
	}

}

然后我们在定义Hello对应的单例bean时,可以new一个匿名的Hello类的子类,然后在其中重写getWorld()方法,对应方法体则是通过@Configuration标注的配置类的对应方法获取一个多例的World实例。这样我们在单例的hello中每次调用getWorld()方法时都会从bean容器中获取到一个全新的World实例。

 

@Configuration
public class SpringConfig {

	@Bean
	public Hello hello() {
		Hello hello = new Hello() {
			public World getWorld() {
				return world();
			}
		};
		return hello;
	}
	
	@Bean
	@Scope("prototype")
	public World world() {
		return new World();
	}
	
}

 

 

本文转自:https://elim.iteye.com/blog/2389618

分享到:
评论

相关推荐

    跟我学spring3(8-13)

    【第十二章】零配置 之 12.4 基于Java类定义Bean配置元数据 ——跟我学spring3 【第十二章】零配置 之 12.5 综合示例-积分商城 ——跟我学spring3 【第十三章】 测试 之 13.1 概述 13.2 单元测试 ——跟我学spring3 ...

    跟我学spring3(1-7)

    【第二章】 IoC 之 2.3 IoC的配置使用——跟我学Spring3 【第三章】 DI 之 3.1 DI的配置使用 ——跟我学spring3 【第三章】 DI 之 3.2 循环依赖 ——跟我学spring3 【第三章】 DI 之 3.3 更多DI的知识 ——跟我学...

    Spring.3.x企业应用开发实战(完整版).part2

    4.11.2 使用基于Java类的配置信息启动Spring容器 4.12 不同配置方式比较 4.13 小结 第5章 Spring容器高级主题 5.1 Spring容器技术内幕 5.1.1 内部工作机制 5.1.2 BeanDefinition 5.1.3 InstantiationStrategy 5.1.4 ...

    spring3.0jar包

    ◆容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一...

    Spring 中文API&开发文档.rar

    ◆容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一...

    spring-framework-3.1.0.RELEASE.zip

    容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个...

    Spring3.x企业应用开发实战(完整版) part1

    4.11.2 使用基于Java类的配置信息启动Spring容器 4.12 不同配置方式比较 4.13 小结 第5章 Spring容器高级主题 5.1 Spring容器技术内幕 5.1.1 内部工作机制 5.1.2 BeanDefinition 5.1.3 InstantiationStrategy 5.1.4 ...

    跟我学spring3(8-13).pdf

    11.2 实现通用层 11.3 实现积分商城层 12.1 概述 12.2 注解实现Bean依赖注入 12.3 注解实现Bean定义 12.4 基于Java类定义Bean配置元数据 12.5 综合示例-积分商城 13.1 概述 13.2 单元测试 集成测试 ——跟我学spring3

    JavaEE开发的颠覆者SpringBoot实战[完整版].part3

    1.3 Spring 基础配置 17 1.3.1 依赖注入 18 1.3.2 Java 配置 21 1.3.3 AOP 24 第2 章 Spring 常用配置 30 2.1 Bean 的Scope 30 2.1.1 点睛 30 2.1.2 示例 31 2.2 Spring EL 和资源调用. 33 2.2.1 点睛 33 2.2.2 示例...

    从Java走向Java+EE+.rar

    第17章 JNDI和Java RMI远程调用 249 17.1 用Java RMI实现远程调用 250 17.2 利用JNDI定位资源 256 17.3 实例——分布式的HelloWorld 260 17.4 小结 264 第18章 Java消息服务 265 18.1 消息系统和JMS 265...

    JavaEE开发的颠覆者SpringBoot实战[完整版].part2

    1.3 Spring 基础配置 17 1.3.1 依赖注入 18 1.3.2 Java 配置 21 1.3.3 AOP 24 第2 章 Spring 常用配置 30 2.1 Bean 的Scope 30 2.1.1 点睛 30 2.1.2 示例 31 2.2 Spring EL 和资源调用. 33 2.2.1 点睛 33 2.2.2 示例...

    Spring 4.x 企业应用开发实战_带目录_源码_高清晰完整版180M

    Spring 4.0引入了众多Java开发者翘首以盼的基于Groovy Bean的配置、H TML 5/WebSocket支持等新功能,全面支持Java 8.0,最低要求是Java 6.0。这些新功能实用性强、易用性高,可大幅降低Java应用,特别是Java Web...

    精通Spring+4.x++企业应用开发实战.zip

    Spring 4.0引入了众多Java开发者翘首以盼的基于Groovy Bean的配置、HTML 5/WebSocket支持等新功能,全面支持Java 8.0,最低要求是Java 6.0。这些新功能实用性强、易用性高,可大幅降低Java应用,特别是Java Web应用...

    Spring4.x企业应用开发实战电子版pdf

    Spring 4.0引入了众多Java开发者翘首以盼的基于Groovy Bean的配置、HTML 5/WebSocket支持等新功能,全面支持Java 8.0,最低要求是Java 6.0。这些新功能实用性强、易用性高,可大幅降低Java应用,特别是Java Web应用...

    精通Spring 4.x 企业应用开发实战.pdf

    Spring 4.0引入了众多Java开发者翘首以盼的基于Groovy Bean的配置、HTML 5/WebSocket支持等新功能,全面支持Java 8.0,最低要求是Java 6.0。这些新功能实用性强、易用性高,可大幅降低Java应用,特别是Java Web应用...

    JavaEE开发的颠覆者SpringBoot实战[完整版].part1

    1.3 Spring 基础配置 17 1.3.1 依赖注入 18 1.3.2 Java 配置 21 1.3.3 AOP 24 第2 章 Spring 常用配置 30 2.1 Bean 的Scope 30 2.1.1 点睛 30 2.1.2 示例 31 2.2 Spring EL 和资源调用. 33 2.2.1 点睛 33 2.2.2 示例...

    精通Spring4.x企业应用开发实战 - part2/2

    Spring 4.0引入了众多Java开发者翘首以盼的基于Groovy Bean的配置、HTML 5/WebSocket支持等新功能,全面支持Java 8.0,最低要求是Java 6.0。这些新功能实用性强、易用性高,可大幅降低Java应用,特别是Java Web应用...

    精通Spring 4.x 企业应用开发实战

    Spring 4.0引入了众多Java开发者翘首以盼的基于Groovy Bean的配置、HTML 5/WebSocket支持等新功能,全面支持Java 8.0,*要求是Java 6.0。这些新功能实用性强、易用性高,可大幅降低Java应用,特别是Java Web应用开发...

    Spring4.x企业应用开发 有书签,很方便查找

    本书是在《精通Spring 3.x——企业应用开发详解》的基础上,历时一年的重大调整改版而成的,延续了上一版本“追求深度,注重原理,不停留在技术表面”的写作风格,力求使读者在熟练使用Spring的各项功能的同时透彻...

Global site tag (gtag.js) - Google Analytics