`

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

分享到:
评论

相关推荐

    使用java类配置Bean

    本文将深入探讨"使用java类配置Bean"这一主题,特别是在SIA实战项目中的应用。 首先,让我们理解Spring框架的核心概念——Bean。在Spring中,Bean是应用程序中的对象,由Spring容器管理其生命周期,包括创建、初始...

    Spring————面试题库

    举例来说,使用ClassPathXmlApplicationContext可以从classpath的XML配置文件中读取应用程序上下文,从而初始化Spring IoC容器,并加载应用程序中定义的所有bean。而FileSystemXmlApplicationContext则从文件系统中...

    普通类调用Spring bean对象

    我们可以创建一个配置类,然后在其中声明bean,使用`@ComponentScan`扫描包含普通类的包,这样Spring就能自动管理普通类。同时,也可以在配置类中使用`@Bean`注解创建bean实例,然后在普通类中通过`@Autowired`注入...

    Spring依赖注入——java项目中使用spring注解方式进行注入.rar

    1. 创建Bean:首先,你需要在Spring配置文件中声明你的bean,或者使用`@Component`、`@Service`、`@Repository`、`@Controller`等注解来标记类,让Spring自动扫描并管理。 2. 注解注入:在需要注入依赖的类中,使用...

    Java EE 框架整合开发⼊⻔到实战——Spring+Spring MVC+MyBatis(微课版)课后习题答案.pdf

    这份文档名为《Java EE 框架整合开发入门到实战——Spring+Spring MVC+MyBatis(微课版)课后习题答案.pdf》,它显然是关于Java EE中流行的三个框架整合使用的教程。这三个框架分别是Spring、Spring MVC和MyBatis,...

    firebird embedded 嵌入式——Spring hibernate 集成连接配置

    你需要在Spring配置文件中定义一个SessionFactoryBean,设置相应的Hibernate配置属性,如hibernate.dialect(针对Firebird的方言)、hibernate.connection.driver_class(Firebird JDBC驱动类)以及数据库连接信息。...

    Quartz Spring整合——附带webservice Demo

    Spring 是一个广泛应用的Java企业级应用开发框架,它提供了全面的编程和配置模型,使得开发复杂应用变得简单。当我们把Quartz与Spring整合时,可以利用Spring的依赖注入(DI)和管理上下文来更方便地控制和管理定时...

    征服Spring AOP—— Schema

    在IT领域,Spring框架是Java开发中的核心组件,尤其在企业级应用中广泛使用。Spring AOP(面向切面编程)是Spring框架的一个重要组成部分,它允许开发者在不修改源代码的情况下,通过“切面”来关注程序的某些方面,...

    二、Spring源码分析——BeanFactory

    《Spring源码分析——BeanFactory》 在Java的IoC(Inversion of Control)和DI(Dependency Injection)领域,Spring框架扮演着至关重要的角色。BeanFactory是Spring的核心组件之一,它是容器的基石,负责管理应用...

    Spring特性——事件驱动模型

    1. **事件(Event)**:在Spring中,事件通常是一个简单的Java类,继承自`java.util.EventObject`。这个类通常包含事件相关的数据,但也可以只是一个空的标记类,用于标识发生了某种类型的事件。例如,我们可以定义...

    SpringCloud——Zookeeper(注册中心)

    SpringCloud Zookeeper配置中心允许动态更新应用程序的配置,无需重启服务。此外,Zookeeper还可以作为分布式锁的实现,解决分布式环境下的并发问题。 总结来说,SpringCloud与Zookeeper的结合,使得开发者能够快速...

    Spring MVC Ibatis Bean 根据mysql数据表——代码生成工具

    标题中的“Spring MVC Ibatis Bean 根据mysql数据表——代码生成工具”就是这样的一个工具,它能够根据MySQL数据库中的表结构,快速生成符合Spring MVC和Ibatis框架的代码。 Rapid-generator-0.2v可能是这个工具的...

    Spring开发指南——中文版

    - 容器通过读取配置元数据(XML、注解或Java配置类)来创建和管理Bean。 5. **Spring的模块** - **核心容器**:包含Core Container(核心容器)、Beans、Context等模块,负责Bean的创建、配置和管理。 - **数据...

    Spring boot——@DeclareParents例子

    当我们在一个切面类中使用`@DeclareParents`时,Spring会为匹配到的bean创建代理,并将指定的接口实现注入到这些bean中。 首先,我们需要了解`@Aspect`的使用。在Spring Boot项目中,创建一个带有`@Aspect`注解的类...

    实例化Spring bean的两种工厂方法

    实例化Spring Bean的方式多种多样,包括XML配置、注解配置以及Java配置等。而工厂方法是其中一种自定义实例化过程的方法。 1. **实例工厂方法** 实例工厂方法是通过一个具体的工厂类实例来创建Spring Bean。在...

    【框架源码篇 04】Spring源码手写篇-Bean定义配置化

    在本篇【框架源码篇 04】中,我们将深入探讨Spring框架的核心概念——Bean定义配置化。Spring是Java领域最广泛使用的依赖注入(Dependency Injection,简称DI)和面向切面编程(Aspect-Oriented Programming,简称...

    MyBatis与Spring整合——通过官方文档进行最简单的整合

    MyBatis可以使用简单的XML或注解来进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。 #### 三、Spring框架简介 Spring框架是用于构建企业级Java应用程序的...

    三、Spring源码分析——ApplicationContext

    Java配置则使用@Configuration和@Bean注解,使得代码更加简洁且易于测试。@ComponentScan则会扫描指定包下的所有@Component注解的类,自动将它们注册为Bean。 2. **Bean的生命周期管理**: ApplicationContext负责...

Global site tag (gtag.js) - Google Analytics