1.3-Spring 基于注解的配置

1,从 Spring 2.5 开始就可以使用注解来配置依赖注入
2,关键字<context:annotation-config/>

注解 描述
@Required 注解应用于 bean 属性的 set 方法
@Autowired 注解可以应用到 bean 属性的 set 方法、非 setter 方法、构造函数、属性
@Qualifier 通过指定确切的将被连线的 bean,@Autowired 和 @Qualifier 注解可以用来删除混乱
JSR-250 Annotations Spring 支持 JSR-250 的基础的注解,其中包括了 @Resource,@PostConstruct 和 @PreDestroy 注解。

@Required

应用于 bean 属性的 set 方法,在配置时必须放在 XML 配置文件中,否则容器就会抛出一个 BeanInitializationException 异常
它的作用相当于byName

public class Student {
   private Integer age;
   private String name;
   @Required
   public void setAge(Integer age) {
      this.age = age;
   }
   public Integer getAge() {
      return age;
   }
   @Required
   public void setName(String name) {
      this.name = name;
   }
   public String getName() {
      return name;
   }
}

如果只配置了name而没有配置age的话,将会引起BeanInitializationException异常,因为有@Required注解的方法必须在bean中配置指明

<context:annotation-config/>

<bean id="student" class="com.xxx.xxx.Student">
    <property name="name"  value="test1" />
    <property name="age"  value="11"/>
</bean>

@Autowired

对在哪里和如何完成自动连接提供了更多的细微的控制
如果在set方法上使用@Autowired ,那么它的作用相当于byType

import org.springframework.beans.factory.annotation.Autowired;
public class Tes1t{
   private Test2 test2;
   @Autowired
   public void setTest2 ( Test2 test2){
      this.test2= test2;
   }
   public Test2  getTest2 ( ) {
      return test2;
   }
}
<context:annotation-config/>

<bean id="test1" class="com.xxx.xxx.Test1"/>

<bean id="test2" class="com.xxx.xxx.Test2"/>

@Autowired也可以直接配置在属性上,这样做相当于赋值于set方法

import org.springframework.beans.factory.annotation.Autowired;
public class Tes1t{
    @Autowired
    private Test2 test2;

    public Test2  getTest2 ( ) {
      return test2;
    }
}

@Autowired也可以直接配置在构造方法上,这样做当这个类被创建的时候,就会set进构造方法所需要的参数

import org.springframework.beans.factory.annotation.Autowired;
public class Tes1t{
   private Test2 test2;
   @Autowired
   public  Tes1t( Test2 test2){
      this.test2= test2;
   }
   public Test2  getTest2 ( ) {
      return test2;
   }
}

@Autowired 的(required=false)选项
默认情况下是true,类似于@Required,参数是必须传递的。
false的话,则参数可以不传递

@Qualifier 注释

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

public class Student {
   private Integer age;
   private String name;
   public void setAge(Integer age) {
      this.age = age;
   }   
   public Integer getAge() {
      return age;
   }
   public void setName(String name) {
      this.name = name;
   }  
   public String getName() {
      return name;
   }
}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class Profile {
   @Autowired
   @Qualifier("student1")
   private Student student;
   public Profile(){
      System.out.println("Inside Profile constructor." );
   }
   public void printAge() {
      System.out.println("Age : " + student.getAge() );
   }
   public void printName() {
      System.out.println("Name : " + student.getName() );
   }
}

我们的bean中有两个student,我们可以使用Qualifier来指定我们需要的是student1还是student2


   <context:annotation-config/>

   <bean id="profile" class="com.xxx.xxx.Profile">
   </bean>

   <bean id="student1" class="com.xxx.xxx.Student">
      <property name="name"  value="test1" />
      <property name="age"  value="11"/>
   </bean>

   <bean id="student2" class="com.xxx.xxx.Student">
      <property name="name"  value="test2" />
      <property name="age"  value="2"/>
   </bean>

JSR-250 注释

它包括 @PostConstruct, @PreDestroy 和 @Resource 注释
@PostConstruct 和 @PreDestroy 注释:
定义你的bean的生命周期
@Resource 注释:
相当于byName

public class Test{
   private Test2 test2;

   @Resource(name= "testTwo")
   public void setMessage(Test2 test2){
      this.test2= test2;
   }
   public Test2 getTest2 (){
      return test2;
   }
   @PostConstruct
   public void init(){
      System.out.println("Bean is going through init.");
   }
   @PreDestroy
   public void destroy(){
      System.out.println("Bean will destroy now.");
   }
}
<context:annotation-config/>

<bean id="test" class="com.xxx.xxx.Test" init-method="init" destroy-method="destroy">

</bean>
<bean id="testTwo" class="com.xxx.xxx.TestTwo"/>

基于 Java 的配置

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

import org.springframework.context.annotation.*;
@Configuration
public class Test{
   @Bean 
   public Test2 test2(){
      return new Test2();
   }
}

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

<beans>
   <bean id="test2" class="com.xxx.xxx.Test2" />
</beans>

解析

ApplicationContext ctx = 
   new AnnotationConfigApplicationContext(Test.class); 

可以加载各种配置类

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
   ctx.register(AppConfig.class, OtherConfig.class);
   ctx.register(AdditionalConfig.class);
   ctx.refresh();
   Test test = ctx.getBean(Test.class);

@Import
允许从另一个配置类中加载 @Bean 定义

@Configuration
public class ConfigA {
   @Bean
   public A a() {
      return new A(); 
   }
}

@Configuration
@Import(ConfigA.class)
public class ConfigB {
   @Bean
   public B a() {
      return new A(); 
   }
}

当实例化上下文时,不需要同时指定 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);
}

生命周期回调

public class Foo {
   public void init() {
      // initialization logic
   }
   public void destroy() {
      // destruction logic
   }
}

@Configuration
public class AppConfig {
   @Bean(initMethod = "init", destroyMethod = "destroy" )
   public Foo foo() {
      return new Foo();
   }
}

@Scope 指定 Bean 的范围
默认范围是单实例

@Configuration
public class AppConfig {
   @Bean
   @Scope("prototype")
   public Foo foo() {
      return new Foo();
   }
}

事件处理

Spring 内置事件 描述
ContextRefreshedEvent 当使用 ConfigurableApplicationContext 接口的 refresh() 方法刷新。ApplicationContext 被初始化或刷新时,该事件也会被发布。
ContextStartedEvent 当使用 ConfigurableApplicationContext 接口中的 start() 方法开始
ContextStoppedEvent 当使用 ConfigurableApplicationContext 接口中的 stop() 方法停止
ContextClosedEvent 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭
RequestHandledEvent 这是一个 web-specific 事件,告诉所有 bean, HTTP 请求已经被服务。

监听上下文事件
一个 bean 应该实现只有一个方法 onApplicationEvent() 的 ApplicationListener 接口

public class Test{
   private String message;
   public void setMessage(String message){
      this.message  = message;
   }
   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
}
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStartedEvent;
public class CStartEventHandler 
   implements ApplicationListener<ContextStartedEvent>{
   public void onApplicationEvent(ContextStartedEvent event) {
      System.out.println("ContextStartedEvent Received");
   }
}
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStoppedEvent;
public class CStopEventHandler 
   implements ApplicationListener<ContextStoppedEvent>{
   public void onApplicationEvent(ContextStoppedEvent event) {
      System.out.println("ContextStoppedEvent Received");
   }
}
   <bean id="test" class="com.xxx.xxx.Test">
      <property name="message" value="Hello World!"/>
   </bean>

   <bean id="cStartEventHandler" 
         class="com.xxx.xxx.CStartEventHandler"/>

   <bean id="cStopEventHandler" 
         class="com.xxx.xxx.CStopEventHandler"/>
 public static void main(String[] args) {
      ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");

      context.start();
      Testobj = (Test) context.getBean("test");
      obj.getMessage();
      context.stop();
   }

自定义事件

import org.springframework.context.ApplicationEvent;
public class CustomEvent extends ApplicationEvent{ 
   public CustomEvent(Object source) {
      super(source);
   }
   public String toString(){
      return "My Custom Event";
   }
}
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
public class CustomEventPublisher 
   implements ApplicationEventPublisherAware {
   private ApplicationEventPublisher publisher;
   public void setApplicationEventPublisher
              (ApplicationEventPublisher publisher){
      this.publisher = publisher;
   }
   public void publish() {
      CustomEvent ce = new CustomEvent(this);
      publisher.publishEvent(ce);
   }
}
import org.springframework.context.ApplicationListener;
public class CustomEventHandler 
   implements ApplicationListener<CustomEvent>{
   public void onApplicationEvent(CustomEvent event) {
      System.out.println(event.toString());
   }
}
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
   public static void main(String[] args) {
      ConfigurableApplicationContext context = 
      new ClassPathXmlApplicationContext("Beans.xml");    
      CustomEventPublisher cvp = 
      (CustomEventPublisher) context.getBean("customEventPublisher");
      cvp.publish();  
      cvp.publish();
   }
}
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="customEventHandler" 
      class="com.xxx.xxx.CustomEventHandler"/>

   <bean id="customEventPublisher" 
      class="com.xxx.xxx.CustomEventPublisher"/>

</beans>
发布了113 篇原创文章 · 获赞 48 · 访问量 34万+

猜你喜欢

转载自blog.csdn.net/yehui928186846/article/details/81270333