配色: 字号:
IOC之基于Java类的配置Bean
2016-10-13 | 阅:  转:  |  分享 
  
IOC之基于Java类的配置Bean



基于Java配置选项,可以编写大多数的spring不用配置XML,但有几个基于Java的注释的帮助下解释。从Spring3.0开始支持使用java代码来代替XML来配置Spring,基于Java配置Spring依靠Spring的JavaConfig项目提供的很多优点。通过使用@Configuration,@Bean,@Importand,@DependsOnannotations来实现Java的配置Spring.

本文工程下载

@Configuration&@Bean注解:

在Spring的新的Java-Configuration的中间产物是基于类的@Configuration的注解和基于方法的@Bean注解。

@Bean注解是用来指明方法的实例化,配置和初始化一个对象是通过Spring的IoC容器来管理的。对于那些熟悉使用以XML配置Spring的标签,@Bean注解和标签是起相同作用的。你能和Spring的@Component注解的组件一起使用@Bean注解方法,然而,这些@Bean注解的方法通常是和@Configuration的Bean。

@Configuration注解的类指明该类主要是作为一个bean的来源定义。此外,@Configurationd定义的classes允许在同一个类中使用@Bean定义的方法来定义依赖的bean

注释类与@Configuration表示这个类可以使用SpringIoC容器为bean定义的来源。在@Bean注解告诉Spring的注解为@Bean的一个方法将返回应注册为在Spring应用程序上下文中的bean对象。最简单可行的@Configuration类将如下所示:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

@Configuration

publicclassCompanyConfig{

@Bean

publicEmployeeemployee(){

returnnewEmployee();

}



}



上面的代码将等同于下面的XML配置:

[html]viewplaincopy在CODE上查看代码片派生到我的代码片



下面注解为@Bean的方法名称作为工作bean的id,它创建并返回实际的bean。配置类可以有声明多个@Bean。一旦配置类定义,可以加载和提供他们使用AnnotationConfigApplicationContext如下,以Spring容器:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicstaticvoidmain(String[]args){

ApplicationContextctx=newAnnotationConfigApplicationContext(CompanyConfig.class);

Employeeemployee=ctx.getBean(Employee.class);

employee.setName("笨笨");

employee.setId(2012);

System.out.println(employee);



}

也可以这样写:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

packagecom.mucfc.anno;



importorg.springframework.context.ApplicationContext;

importorg.springframework.context.annotation.AnnotationConfigApplicationContext;

importorg.springframework.context.support.ClassPathXmlApplicationContext;



publicclassTest{

publicstaticvoidmain(String[]args){



AnnotationConfigApplicationContextctx=newAnnotationConfigApplicationContext();

ctx.register(CompanyConfig.class);

ctx.refresh();

Employeeemployee1=ctx.getBean(Employee.class);

Employeeemployee2=ctx.getBean(Employee.class);



employee1.setName("笨笨");

employee1.setId(2012);



employee2.setName("狂人");

employee2.setId(34546);



System.out.println("exployee1"+employee1);

System.out.println("exployee2"+employee2);

System.out.print("employee1==employee2?:");

System.out.print(employee1==employee2);



}



}





把上面的@Bean加个@scope

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

packagecom.mucfc.anno;



importorg.springframework.context.annotation.Bean;

importorg.springframework.context.annotation.Configuration;

importorg.springframework.context.annotation.Scope;



@Configuration

publicclassCompanyConfig{

@Bean

@Scope("singleton")

publicEmployeeemployee(){

returnnewEmployee();

}



}

其它不变。运行结果:





说明默认返回的是singleton类型,这里改成了prototpye

这么做有什么好处呢?

1.使用纯java代码,不在需要xml

2.在配置中也可享受OO带来的好处

3.类型安全对重构也能提供良好的支持

4.依旧能享受到所有springIoC容器提供的功能



ApplicationContext接口的最常用的实现类是ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,以及面向Portlet的XmlPortletApplicationContext和面向web的XmlWebApplicationContext,它们都是面向XML的。Spring3.0新增了另外两个实现类:AnnotationConfigApplicationContext和AnnotationConfigWebApplicationContext。从名字便可以看出,它们是为注解而生,直接依赖于注解作为容器配置信息来源的IoC容器初始化类。由于AnnotationConfigWebApplicationContext是AnnotationConfigApplicationContext的web版本,其用法与后者相比几乎没有什么差别,因此本文将以AnnotationConfigApplicationContext为例进行讲解。

AnnotationConfigApplicationContext搭配上@Configuration和@Bean注解,自此,XML配置方式不再是SpringIoC容器的唯一配置方式。两者在一定范围内存在着竞争的关系,但是它们在大多数情况下还是相互协作的关系,两者的结合使得SpringIoC容器的配置更简单,更强大。之前,我们将配置信息集中写在XML中,如今使用注解,配置信息的载体由XML文件转移到了Java类中。我们通常将用于存放配置信息的类的类名以“Config”结尾,比如AppDaoConfig.java、AppServiceConfig.java等等。我们需要在用于指定配置信息的类上加上@Configuration注解,以明确指出该类是Bean配置的信息源。

注意:Spring对标注Configuration的类有如下要求

配置类不能是final的;配置类不能是本地化的,亦即不能将配置类定义在其他类的方法内部;配置类必须有一个无参构造函数。AnnotationConfigApplicationContext将配置类中标注了@Bean的方法的返回值识别为SpringBean,并注册到容器中,受IoC容器管理。@Bean的作用等价于XML配置中的标签。

@Bean具有以下四个属性:

name--指定一个或者多个Bean的名字。这等价于XML配置中的name属性。

initMethod--容器在初始化完Bean之后,会调用该属性指定的方法。这等价于XML配置中的init-method属性。

destroyMethod--该属性与initMethod功能相似,在容器销毁Bean之前,会调用该属性指定的方法。这等价于XML配置中的destroy-method属性。

autowire--指定Bean属性的自动装配策略,取值是Autowire类型的三个静态属性。Autowire.BY_NAME,Autowire.BY_TYPE,Autowire.NO。与XML配置中的autowire属性的取值相比,这里少了constructor,这是因为constructor在这里已经没有意义了。@Bean没有直接提供指定作用域的属性,可以通过@Scope来实现该功能。



由于@configureation注解类本身已经标注了@component注解,所以任何标注了@configuration的类,本身也相当于标注了@component,即它们可以像普通的bean一样被注入到其它bean中去。

如下面:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

packagecom.mucfc.anno;



importorg.springframework.beans.factory.annotation.Autowired;

importorg.springframework.context.annotation.Configuration;



@Configuration

publicclassCompany{

@Autowired

//自动装配Configuration定义好的CompanyConfig

privateCompanyConfigcompanyConfig;



publicCompanyConfiggetCompanyConfig(){

returncompanyConfig;

}



publicvoidsetCompanyConfig(CompanyConfigcompanyConfig){

this.companyConfig=companyConfig;

}



}

使用:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

ctx.register(CompanyConfig.class);

ctx.register(Company.class);

ctx.refresh();



[java]viewplaincopy在CODE上查看代码片派生到我的代码片

Employeeemployee3=ctx.getBean(Company.class).getCompanyConfig().employee();

employee3.setName("红色革命");

employee3.setId(2342);

System.out.println("exployee3"+employee3);



输出结果:

exployee3员工姓名:红色革命员工编号:2342



使用基于java类的配置信息启动Spring容器:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

/AnnotationConfigApplicationContextctx=newAnnotationConfigApplicationContext();

ctx.register(CompanyConfig.class);

ctx.register(Company.class);

ctx.refresh();/

ApplicationContextctx=newAnnotationConfigApplicationContext(CompanyConfig.class);

其中注释的代码和不注释的代码可以看成是相同的,运行后结果不

@Import注解:

@import的注解允许加载@Bean从另一个配置类定义。考虑一个配置类,如下所示:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

@Configuration

publicclassConfigA{

@Bean

publicAa(){

returnnewA();

}

}

您可以在另一个bean声明导入上述bean声明如下

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

@Configuration

@Import(ConfigA.class)

publicclassConfigB{

@Bean

publicBa(){

returnnewA();

}

}



现在,不需要实例化的前提下,当同时指定配置A.class和配置B.class,只有ConfigB类需要如下提供:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicstaticvoidmain(String[]args){

ApplicationContextctx=

newAnnotationConfigApplicationContext(ConfigB.class);

//nowwww.baiyuewang.netbothbeansAandBwillbeavailable...

Aa=ctx.getBean(A.class);

Bb=ctx.getBean(B.class);

}

生命周期回调:

@Bean注解支持指定任意的初始化和销毁??回调方法,就像Spring的XML的初始化方法和bean元素销毁方法的属性:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicclassFoo{

publicvoidinit(){

//initializationlogic

}

publicvoidcleanup(){

//destructionlogic

}

}



@Configuration

publicclassAppConfig{

@Bean(initMethod="init",destroyMethod="cleanup")

publicFoofoo(){

returnnewFoo();

}

}

指定Bean的适用范围:

默认范围是单例,但可以使用@Scope注解来覆盖此如下:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

@Configuration

publicclassAppConfig{

@Bean

@Scope("prototype")

publicFoofoo(){

returnnewFoo();

}

}



三种配置bean方式的对比总结







献花(0)
+1
(本文系thedust79首藏)