5.Spring 基于注解的配置

1.Spring 基于注解的配置

基于注解的配置

从 Spring 2.5 开始就可以使用注解来配置依赖注入。而不是采用 XML 来描述一个 bean 连线,你可以使用相关类,方法或字段声明的注解,将 bean 配置移动到组件类本身。

在 XML 注入之前进行注解注入,因此后者的配置将通过两种方式的属性连线被前者重写。

注解连线在默认情况下在 Spring 容器中不打开。因此,在可以使用基于注解的连线之前,我们将需要在我们的 Spring 配置文件中启用它。所以如果你想在 Spring 应用程序中使用的任何注解,可以考虑到下面的配置文件。

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns:context="http://www.springframework.org/schema/context"

    xsi:schemaLocation="http://www.springframework.org/schema/beans

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

 

 

一旦 被配置后,你就可以开始注解你的代码,表明 Spring 应该自动连接值到属性,方法和构造函数。让我们来看看几个重要的注解,并且了解它们是如何工作的:

序号注解 & 描述

1@Required

@Required 注解应用于 bean 属性的 setter 方法。

2@Autowired

@Autowired 注解可以应用到 bean 属性的 setter 方法,非 setter 方法,构造函数和属性。

3@Qualifier

通过指定确切的将被连线的 bean,@Autowired 和 @Qualifier 注解可以用来删除混乱。

4JSR-250 Annotations

Spring 支持 JSR-250 的基础的注解,其中包括了 @Resource,@PostConstruct 和 @PreDestroy 注解。



2.Spring @Required 注释

Spring @Required 注释

@Required 注释应用于 bean 属性的 setter 方法,它表明受影响的 bean 属性在配置时必须放在 XML 配置文件中,否则容器就会抛出一个 BeanInitializationException 异常。下面显示的是一个使用 @Required 注释的示例。

示例:

让我们使 Eclipse IDE 处于工作状态,请按照下列步骤创建一个 Spring 应用程序:

步骤描述

1创建一个名为 SpringExample 的项目,并且在所创建项目的 src 文件夹下创建一个名为 com.tutorialspoint 的包。

2使用 Add External JARs 选项添加所需的 Spring 库文件,就如在 Spring Hello World Example 章节中解释的那样。

3在 com.tutorialspoint 包下创建 Java 类 Student 和 MainApp

4在 src 文件夹下创建 Beans 配置文件 Beans.xml

5最后一步是创建所有 Java 文件和 Bean 配置文件的内容,并且按如下解释的那样运行应用程序。

下面是 Student.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.beans.factory.annotation.Required;publicclassStudent{privateInteger age;privateString name;@RequiredpublicvoidsetAge(Integer age){this.age = age;  }publicIntegergetAge(){returnage;  }@RequiredpublicvoidsetName(String name){this.name = name;  }publicStringgetName(){returnname;  }}

下面是 MainApp.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassMainApp{publicstaticvoidmain(String[] args){      ApplicationContext context =newClassPathXmlApplicationContext("Beans.xml");      Student student = (Student) context.getBean("student");      System.out.println("Name : "+ student.getName() );      System.out.println("Age : "+ student.getAge() );  }}

下面是配置文件 Beans.xml: 文件的内容:

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context-3.0.xsd">                         

一旦你已经完成的创建了源文件和 bean 配置文件,让我们运行一下应用程序。如果你的应用程序一切都正常的话,这将引起 BeanInitializationException 异常,并且会输出一下错误信息和其他日志消息:

Property'age'is requiredforbean'student'

下一步,在你按照如下所示从 “age” 属性中删除了注释,你可以尝试运行上面的示例:

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context-3.0.xsd">                   

现在上面的示例将产生如下结果:

Name : ZaraAge :11



3.Spring @Autowired 注释

Spring @Autowired 注释

@Autowired 注释对在哪里和如何完成自动连接提供了更多的细微的控制。

@Autowired 注释可以在 setter 方法中被用于自动连接 bean,就像 @Autowired 注释,容器,一个属性或者任意命名的可能带有多个参数的方法。

Setter 方法中的 @Autowired

你可以在 XML 文件中的 setter 方法中使用 @Autowired 注释来除去 元素。当 Spring遇到一个在 setter 方法中使用的 @Autowired 注释,它会在方法中视图执行 byType 自动连接。

示例

让我们使 Eclipse IDE 处于工作状态,然后按照如下步骤创建一个 Spring 应用程序:

步骤描述

1创建一个名为 SpringExample 的项目,并且在所创建项目的 src 文件夹下创建一个名为 com.tutorialspoint 的包。

2使用 Add External JARs 选项添加所需的 Spring 库文件,就如在 Spring Hello World Example 章节中解释的那样。

3在 com.tutorialspoint 包下创建 Java 类 TextEditorSpellChecker 和 MainApp

4在 src 文件夹下创建 Beans 配置文件 Beans.xml

5最后一步是创建所有 Java 文件和 Bean 配置文件的内容,并且按如下解释的那样运行应用程序。

这里是 TextEditor.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.beans.factory.annotation.Autowired;publicclassTextEditor{privateSpellChecker spellChecker;@AutowiredpublicvoidsetSpellChecker( SpellChecker spellChecker ){this.spellChecker = spellChecker;  }publicSpellCheckergetSpellChecker( ){returnspellChecker;  }publicvoidspellCheck(){      spellChecker.checkSpelling();  }}

下面是另一个依赖的类文件 SpellChecker.java 的内容:

packagecom.tutorialspoint;publicclassSpellChecker{publicSpellChecker(){      System.out.println("Inside SpellChecker constructor.");  }publicvoidcheckSpelling(){      System.out.println("Inside checkSpelling.");  }  }

下面是 MainApp.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassMainApp{publicstaticvoidmain(String[] args){      ApplicationContext context =newClassPathXmlApplicationContext("Beans.xml");      TextEditor te = (TextEditor) context.getBean("textEditor");      te.spellCheck();  }}

下面是配置文件 Beans.xml

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context-3.0.xsd">             

一旦你已经完成的创建了源文件和 bean 配置文件,让我们运行一下应用程序。如果你的应用程序一切都正常的话,这将会输出以下消息:

Inside SpellChecker constructor.

Inside checkSpelling.

属性中的 @Autowired

你可以在属性中使用 @Autowired 注释来除去 setter 方法。当时使用 为自动连接属性传递的时候,Spring 会将这些传递过来的值或者引用自动分配给那些属性。所以利用在属性中 @Autowired 的用法,你的 TextEditor.java 文件将变成如下所示:

packagecom.tutorialspoint;importorg.springframework.beans.factory.annotation.Autowired;publicclassTextEditor{@AutowiredprivateSpellChecker spellChecker;publicTextEditor(){      System.out.println("Inside TextEditor constructor.");  }publicSpellCheckergetSpellChecker( ){returnspellChecker;  }publicvoidspellCheck(){      spellChecker.checkSpelling();  }}

下面是配置文件 Beans.xml

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context-3.0.xsd">             

一旦你在源文件和 bean 配置文件中完成了上面两处改变,让我们运行一下应用程序。如果你的应用程序一切都正常的话,这将会输出以下消息:

Inside TextEditor constructor.

Inside SpellChecker constructor.

Inside checkSpelling.

构造函数中的 @Autowired

你也可以在构造函数中使用 @Autowired。一个构造函数 @Autowired 说明当创建 bean 时,即使在 XML 文件中没有使用 元素配置 bean ,构造函数也会被自动连接。让我们检查一下下面的示例。

这里是 TextEditor.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.beans.factory.annotation.Autowired;publicclassTextEditor{privateSpellChecker spellChecker;@AutowiredpublicTextEditor(SpellChecker spellChecker){      System.out.println("Inside TextEditor constructor.");this.spellChecker = spellChecker;  }publicvoidspellCheck(){      spellChecker.checkSpelling();  }}

下面是配置文件 Beans.xml

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context-3.0.xsd">             

一旦你在源文件和 bean 配置文件中完成了上面两处改变,让我们运行一下应用程序。如果你的应用程序一切都正常的话,这将会输出以下消息:

Inside SpellChecker constructor.Inside TextEditor constructor.Inside checkSpelling.

@Autowired 的(required=false)选项

默认情况下,@Autowired 注释意味着依赖是必须的,它类似于 @Required 注释,然而,你可以使用 @Autowired 的 (required=false) 选项关闭默认行为。

即使你不为 age 属性传递任何参数,下面的示例也会成功运行,但是对于 name 属性则需要一个参数。你可以自己尝试一下这个示例,因为除了只有 Student.java 文件被修改以外,它和 @Required 注释示例是相似的。

packagecom.tutorialspoint;importorg.springframework.beans.factory.annotation.Autowired;publicclassStudent{privateInteger age;privateString name;@Autowired(required=false)publicvoidsetAge(Integer age){this.age = age;  }publicIntegergetAge(){returnage;  }@AutowiredpublicvoidsetName(String name){this.name = name;  }publicStringgetName(){returnname;  }}


4.Spring @Qualifier 注释

Spring @Qualifier 注释

可能会有这样一种情况,当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱。下面显示的是使用 @Qualifier 注释的一个示例。

示例

让我们使 Eclipse IDE 处于工作状态,请按照下列步骤创建一个 Spring 应用程序:

步骤描述

1创建一个名为 SpringExample 的项目,并且在所创建项目的 src 文件夹下创建一个名为 com.tutorialspoint 的包。

2使用 Add External JARs 选项添加所需的 Spring 库文件,就如在 Spring Hello World Example 章节中解释的那样。

3在 com.tutorialspoint 包下创建 Java 类 StudentProfile 和 MainApp

4在 src 文件夹下创建 Beans 配置文件 Beans.xml

5最后一步是创建所有 Java 文件和 Bean 配置文件的内容,并且按如下解释的那样运行应用程序。

这里是 Student.java 文件的内容:

packagecom.tutorialspoint;publicclassStudent{privateInteger age;privateString name;publicvoidsetAge(Integer age){this.age = age;  }publicIntegergetAge(){returnage;  }publicvoidsetName(String name){this.name = name;  }publicStringgetName(){returnname;  }}

这里是 Profile.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.beans.factory.annotation.Qualifier;publicclassProfile{@Autowired@Qualifier("student1")privateStudent student;publicProfile(){      System.out.println("Inside Profile constructor.");  }publicvoidprintAge(){      System.out.println("Age : "+ student.getAge() );  }publicvoidprintName(){      System.out.println("Name : "+ student.getName() );  }}

下面是 MainApp.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassMainApp{publicstaticvoidmain(String[] args){      ApplicationContext context =newClassPathXmlApplicationContext("Beans.xml");      Profile profile = (Profile) context.getBean("profile");      profile.printAge();      profile.printName();  }}

考虑下面配置文件 Beans.xml 的示例:

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context-3.0.xsd">                                           

一旦你在源文件和 bean 配置文件中完成了上面两处改变,让我们运行一下应用程序。如果你的应用程序一切都正常的话,这将会输出以下消息:

Inside Profile constructor.Age :11Name : Zara


5.Spring JSR-250 注释

Spring JSR-250 注释

Spring还使用基于 JSR-250 注释,它包括 @PostConstruct, @PreDestroy 和 @Resource 注释。因为你已经有了其他的选择,尽管这些注释并不是真正所需要的,但是关于它们仍然让我给出一个简短的介绍。

@PostConstruct 和 @PreDestroy 注释:

为了定义一个 bean 的安装和卸载,我们使用 init-method 和/或 destroy-method 参数简单的声明一下 。init-method 属性指定了一个方法,该方法在 bean 的实例化阶段会立即被调用。同样地,destroy-method 指定了一个方法,该方法只在一个 bean 从容器中删除之前被调用。

你可以使用 @PostConstruct 注释作为初始化回调函数的一个替代,@PreDestroy 注释作为销毁回调函数的一个替代,其解释如下示例所示。

示例

让我们使 Eclipse IDE 处于工作状态,请按照下列步骤创建一个 Spring 应用程序:

步骤描述

1创建一个名为 SpringExample 的项目,并且在所创建项目的 src 文件夹下创建一个名为 com.tutorialspoint 的包。

2使用 Add External JARs 选项添加所需的 Spring 库文件,就如在 Spring Hello World Example 章节中解释的那样。

3在 com.tutorialspoint 包下创建 Java 类 HelloWorld 和 MainApp

4在 src 文件夹下创建 Beans 配置文件 Beans.xml

5最后一步是创建所有 Java 文件和 Bean 配置文件的内容,并且按如下解释的那样运行应用程序。

这里是 HelloWorld.java 文件的内容:

packagecom.tutorialspoint;importjavax.annotation.*;publicclassHelloWorld{privateString message;publicvoidsetMessage(String message){this.message  = message;  }publicStringgetMessage(){      System.out.println("Your Message : "+ message);returnmessage;  }@PostConstructpublicvoidinit(){      System.out.println("Bean is going through init.");  }@PreDestroypublicvoiddestroy(){      System.out.println("Bean will destroy now.");  }}

下面是 MainApp.java 文件的内容。这里你需要注册一个关闭钩 registerShutdownHook() 方法,该方法在 AbstractApplicationContext 类中被声明。这将确保一个完美的关闭并调用相关的销毁方法。

packagecom.tutorialspoint;importorg.springframework.context.support.AbstractApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassMainApp{publicstaticvoidmain(String[] args){      AbstractApplicationContext context =newClassPathXmlApplicationContext("Beans.xml");      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");      obj.getMessage();      context.registerShutdownHook();  }}

下面是配置文件 Beans.xml,该文件在初始化和销毁方法中需要使用。

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context-3.0.xsd">           

一旦你在源文件和 bean 配置文件中完成了上面两处改变,让我们运行一下应用程序。如果你的应用程序一切都正常的话,这将会输出以下消息:

Bean is going through init.

Your Message : Hello World!

Bean will destroy now.

@Resource 注释:

你可以在字段中或者 setter 方法中使用 @Resource 注释,它和在 Java EE 5 中的运作是一样的。@Resource 注释使用一个 ‘name’ 属性,该属性以一个 bean 名称的形式被注入。你可以说,它遵循 by-name 自动连接语义,如下面的示例所示:

packagecom.tutorialspoint;importjavax.annotation.Resource;publicclassTextEditor{privateSpellChecker spellChecker;@Resource(name="spellChecker")publicvoidsetSpellChecker( SpellChecker spellChecker ){this.spellChecker = spellChecker;  }publicSpellCheckergetSpellChecker(){returnspellChecker;  }publicvoidspellCheck(){      spellChecker.checkSpelling();  }}

如果没有明确地指定一个 ‘name’,默认名称源于字段名或者 setter 方法。在字段的情况下,它使用的是字段名;在一个 setter 方法情况下,它使用的是 bean 属性名称。


6.Spring 基于 Java 的配置

基于 Java 的配置

到目前为止,你已经看到如何使用 XML 配置文件来配置 Spring bean。如果你熟悉使用 XML 配置,那么我会说,不需要再学习如何进行基于 Java 的配置是,因为你要达到相同的结果,可以使用其他可用的配置。

基于 Java 的配置选项,可以使你在不用配置 XML 的情况下编写大多数的 Spring,但是一些有帮助的基于 Java 的注解,解释如下:

@Configuration 和 @Bean 注解

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

packagecom.tutorialspoint;importorg.springframework.context.annotation.*;@ConfigurationpublicclassHelloWorldConfig{@BeanpublicHelloWorldhelloWorld(){returnnewHelloWorld();  }}

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

在这里,带有 @Bean 注解的方法名称作为 bean 的 ID,它创建并返回实际的 bean。你的配置类可以声明多个 @Bean。一旦定义了配置类,你就可以使用 AnnotationConfigApplicationContext 来加载并把他们提供给 Spring 容器,如下所示:

publicstaticvoidmain(String[] args){  ApplicationContext ctx =newAnnotationConfigApplicationContext(HelloWorldConfig.class);    HelloWorld helloWorld = ctx.getBean(HelloWorld.class);  helloWorld.setMessage("Hello World!");  helloWorld.getMessage();}

你可以加载各种配置类,如下所示:

publicstaticvoidmain(String[] args){  AnnotationConfigApplicationContext ctx =newAnnotationConfigApplicationContext();  ctx.register(AppConfig.class, OtherConfig.class);  ctx.register(AdditionalConfig.class);  ctx.refresh();  MyService myService = ctx.getBean(MyService.class);  myService.doStuff();}

例子

让我们在恰当的位置使用 Eclipse IDE,然后按照下面的步骤来创建一个 Spring 应用程序:

步骤描述

1创建一个名称为 SpringExample 的项目,并且在创建项目的 src 文件夹中创建一个包 com.tutorialspoint

2使用 Add External JARs 选项,添加所需的 Spring 库,解释见 Spring Hello World Example 章节。

3因为你是使用基于 java 的注解,所以你还需要添加来自 Java 安装目录的 CGLIB.jar 和可以从 asm.ow2.org 中下载的 ASM.jar 库。

4在 com.tutorialspoint 包中创建 Java 类 HelloWorldConfigHelloWorld 和 MainApp

5最后一步是创建的所有 Java 文件和 Bean 配置文件的内容,并运行应用程序,解释如下所示。

这里是 HelloWorldConfig.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.annotation.*;@ConfigurationpublicclassHelloWorldConfig{@BeanpublicHelloWorldhelloWorld(){returnnewHelloWorld();  }}

这里是 HelloWorld.java 文件的内容:

packagecom.tutorialspoint;publicclassHelloWorld{privateString message;publicvoidsetMessage(String message){this.message  = message;  }publicvoidgetMessage(){      System.out.println("Your Message : "+ message);  }}

下面是 MainApp.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.*;publicclassMainApp{publicstaticvoidmain(String[] args){      ApplicationContext ctx =newAnnotationConfigApplicationContext(HelloWorldConfig.class);      HelloWorld helloWorld = ctx.getBean(HelloWorld.class);      helloWorld.setMessage("Hello World!");      helloWorld.getMessage();  }}

一旦你完成了创建所有的源文件并添加所需的额外的库后,我们就可以运行该应用程序。你应该注意这里不需要配置文件。如果你的应用程序一切都正常,将输出以下信息:

Your Message : Hello World!

注入 Bean 的依赖性

当 @Beans 依赖对方时,表达这种依赖性非常简单,只要有一个 bean 方法调用另一个,如下所示:

packagecom.tutorialspoint;importorg.springframework.context.annotation.*;@ConfigurationpublicclassAppConfig{@BeanpublicFoofoo(){returnnewFoo(bar());  }@BeanpublicBarbar(){returnnewBar();  }}

这里,foo Bean 通过构造函数注入来接收参考基准。现在,让我们看到一个正在执行的例子:

例子:

让我们在恰当的位置使用 Eclipse IDE,然后按照下面的步骤来创建一个 Spring 应用程序:

步骤描述

1创建一个名称为 SpringExample 的项目,并且在创建项目的 src 文件夹中创建一个包 com.tutorialspoint

2使用 Add External JARs 选项,添加所需的 Spring 库,解释见 Spring Hello World Example 章节。

3因为你是使用基于 java 的注解,所以你还需要添加来自 Java 安装目录的 CGLIB.jar 和可以从 asm.ow2.org 中下载的 ASM.jar 库。

4在 com.tutorialspoint 包中创建 Java 类 TextEditorConfigTextEditorSpellChecker 和 MainApp

5最后一步是创建的所有 Java 文件和 Bean 配置文件的内容,并运行应用程序,解释如下所示。

这里是 TextEditorConfig.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.annotation.*;@ConfigurationpublicclassTextEditorConfig{@BeanpublicTextEditortextEditor(){returnnewTextEditor( spellChecker() );  }@BeanpublicSpellCheckerspellChecker(){returnnewSpellChecker( );  }}

这里是 TextEditor.java 文件的内容:

packagecom.tutorialspoint;publicclassTextEditor{privateSpellChecker spellChecker;publicTextEditor(SpellChecker spellChecker){      System.out.println("Inside TextEditor constructor.");this.spellChecker = spellChecker;  }publicvoidspellCheck(){      spellChecker.checkSpelling();  }}

下面是另一个依赖的类文件 SpellChecker.java 的内容:

packagecom.tutorialspoint;publicclassSpellChecker{publicSpellChecker(){      System.out.println("Inside SpellChecker constructor.");  }publicvoidcheckSpelling(){      System.out.println("Inside checkSpelling.");  }}

下面是 MainApp.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.*;publicclassMainApp{publicstaticvoidmain(String[] args){      ApplicationContext ctx =newAnnotationConfigApplicationContext(TextEditorConfig.class);      TextEditor te = ctx.getBean(TextEditor.class);      te.spellCheck();  }}

一旦你完成了创建所有的源文件并添加所需的额外的库后,我们就可以运行该应用程序。你应该注意这里不需要配置文件。如果你的应用程序一切都正常,将输出以下信息:

Inside SpellChecker constructor.

Inside TextEditor constructor.

Inside checkSpelling.

@Import 注解:

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

@ConfigurationpublicclassConfigA{@BeanpublicAa(){returnnewA();    }}

你可以在另一个 Bean 声明中导入上述 Bean 声明,如下所示:

@Configuration@Import(ConfigA.class)publicclassConfigB{@BeanpublicBa(){returnnewA();    }}

现在,当实例化上下文时,不需要同时指定 ConfigA.class 和 ConfigB.class,只有 ConfigB 类需要提供,如下所示:

publicstaticvoidmain(String[] args){  ApplicationContext ctx =newAnnotationConfigApplicationContext(ConfigB.class);// now both beans A and B will be available...A a = ctx.getBean(A.class);  B b = ctx.getBean(B.class);}

生命周期回调

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

publicclassFoo{publicvoidinit(){// initialization logic}publicvoidcleanup(){// destruction logic}}@ConfigurationpublicclassAppConfig{@Bean(initMethod ="init", destroyMethod ="cleanup")publicFoofoo(){returnnewFoo();  }}

指定 Bean 的范围:

默认范围是单实例,但是你可以重写带有 @Scope 注解的该方法,如下所示:

@ConfigurationpublicclassAppConfig{@Bean@Scope("prototype")publicFoofoo(){returnnewFoo();  }}



7.Spring 中的事件处理

Spring 中的事件处理

你已经看到了在所有章节中 Spring 的核心是 ApplicationContext,它负责管理 beans 的完整生命周期。当加载 beans 时,ApplicationContext 发布某些类型的事件。例如,当上下文启动时,ContextStartedEvent 发布,当上下文停止时,ContextStoppedEvent 发布。

通过 ApplicationEvent 类和 ApplicationListener 接口来提供在 ApplicationContext 中处理事件。如果一个 bean 实现 ApplicationListener,那么每次 ApplicationEvent 被发布到 ApplicationContext 上,那个 bean 会被通知。

Spring 提供了以下的标准事件:

序号Spring 内置事件 & 描述

1ContextRefreshedEvent

ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext 接口中使用 refresh() 方法来发生。

2ContextStartedEvent

当使用 ConfigurableApplicationContext 接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。

3ContextStoppedEvent

当使用 ConfigurableApplicationContext 接口中的 stop() 方法停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。

4ContextClosedEvent

当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。

5RequestHandledEvent

这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。

由于 Spring 的事件处理是单线程的,所以如果一个事件被发布,直至并且除非所有的接收者得到的该消息,该进程被阻塞并且流程将不会继续。因此,如果事件处理被使用,在设计应用程序时应注意。

监听上下文事件

为了监听上下文事件,一个 bean 应该实现只有一个方法 onApplicationEvent() 的 ApplicationListener 接口。因此,我们写一个例子来看看事件是如何传播的,以及如何可以用代码来执行基于某些事件所需的任务。

让我们在恰当的位置使用 Eclipse IDE,然后按照下面的步骤来创建一个 Spring 应用程序:

步骤描述

1创建一个名称为 SpringExample 的项目,并且在创建项目的 src 文件夹中创建一个包 com.tutorialspoint。

2使用 Add External JARs 选项,添加所需的 Spring 库,解释见 Spring Hello World Example 章节。

3在 com.tutorialspoint 包中创建 Java 类 HelloWorld、CStartEventHandler、CStopEventHandler 和 MainApp。

4在 src 文件夹中创建 Bean 的配置文件 Beans.xml。

5最后一步是创建的所有 Java 文件和 Bean 配置文件的内容,并运行应用程序,解释如下所示。

这里是 HelloWorld.java 文件的内容:

packagecom.tutorialspoint;publicclass HelloWorld {privateString message;public void setMessage(String message){this.message  = message;  }public void getMessage(){      System.out.println("Your Message : "+ message);  }}

下面是 CStartEventHandler.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.ApplicationListener;importorg.springframework.context.event.ContextStartedEvent;publicclass CStartEventHandler

  implements ApplicationListener{public void onApplicationEvent(ContextStartedEvent event) {      System.out.println("ContextStartedEvent Received");  }}

下面是 CStopEventHandler.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.ApplicationListener;importorg.springframework.context.event.ContextStoppedEvent;publicclass CStopEventHandler

  implements ApplicationListener{public void onApplicationEvent(ContextStoppedEvent event) {      System.out.println("ContextStoppedEvent Received");  }}

下面是 MainApp.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.ConfigurableApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclass MainApp {public static void main(String[] args) {      ConfigurableApplicationContext context =newClassPathXmlApplicationContext("Beans.xml");// Let us raise a start event.context.start();      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");      obj.getMessage();// Let us raise a stop event.context.stop();  }}

下面是配置文件 Beans.xml 文件:

        class="com.tutorialspoint.CStartEventHandler"/>

        class="com.tutorialspoint.CStopEventHandler"/>

一旦你完成了创建源和 bean 的配置文件,我们就可以运行该应用程序。如果你的应用程序一切都正常,将输出以下消息:

ContextStartedEventReceivedYour Message : Hello World!ContextStoppedEvent Received



8.Spring 中的自定义事件

Spring 中的自定义事件

编写和发布自己的自定义事件有许多步骤。按照在这一章给出的说明来编写,发布和处理自定义 Spring 事件。

步骤描述

1创建一个名称为 SpringExample 的项目,并且在创建项目的 src 文件夹中创建一个包 com.tutorialspoint。

2使用 Add External JARs 选项,添加所需的 Spring 库,解释见 Spring Hello World Example 章节。

3通过扩展 ApplicationEvent,创建一个事件类 CustomEvent。这个类必须定义一个默认的构造函数,它应该从 ApplicationEvent 类中继承的构造函数。

4一旦定义事件类,你可以从任何类中发布它,假定 EventClassPublisher 实现了 ApplicationEventPublisherAware。你还需要在 XML 配置文件中声明这个类作为一个 bean,之所以容器可以识别 bean 作为事件发布者,是因为它实现了 ApplicationEventPublisherAware 接口。

5发布的事件可以在一个类中被处理,假定 EventClassHandler 实现了 ApplicationListener 接口,而且实现了自定义事件的 onApplicationEvent 方法。

6在 src 文件夹中创建 bean 的配置文件 Beans.xml 和 MainApp 类,它可以作为一个 Spring 应用程序来运行。

7最后一步是创建的所有 Java 文件和 Bean 配置文件的内容,并运行应用程序,解释如下所示。

这个是 CustomEvent.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.ApplicationEvent;publicclassCustomEventextendsApplicationEvent{publicCustomEvent(Object source){super(source);  }publicStringtoString(){return"My Custom Event";  }}

下面是 CustomEventPublisher.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.ApplicationEventPublisher;importorg.springframework.context.ApplicationEventPublisherAware;publicclassCustomEventPublisherimplementsApplicationEventPublisherAware{privateApplicationEventPublisher publisher;publicvoidsetApplicationEventPublisher(ApplicationEventPublisher publisher){this.publisher = publisher;  }publicvoidpublish(){      CustomEvent ce =newCustomEvent(this);      publisher.publishEvent(ce);  }}

下面是 CustomEventHandler.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.ApplicationListener;publicclassCustomEventHandlerimplementsApplicationListener{publicvoidonApplicationEvent(CustomEvent event){      System.out.println(event.toString());  }}

下面是 MainApp.java 文件的内容:

packagecom.tutorialspoint;importorg.springframework.context.ConfigurableApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassMainApp{publicstaticvoidmain(String[] args){      ConfigurableApplicationContext context =newClassPathXmlApplicationContext("Beans.xml");          CustomEventPublisher cvp =      (CustomEventPublisher) context.getBean("customEventPublisher");      cvp.publish();        cvp.publish();  }}

下面是配置文件 Beans.xml

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

一旦你完成了创建源和 bean 的配置文件后,我们就可以运行该应用程序。如果你的应用程序一切都正常,将输出以下信息:

My Custom Event

My Custom Event

你可能感兴趣的:(5.Spring 基于注解的配置)