Spring(七)

Posted 小企鹅推雪球!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring(七)相关的知识,希望对你有一定的参考价值。

Spring基于注解的配置

  1. 我们可以使用注解来配置依赖注入。而不是采用 XML 来描述一个 bean 连线,可以使用相关类,方法或字段声明的注解,将bean配置移动到组件类本身
  2. 在 XML 注入之前进行注解注入,因此后者的配置将通过两种方式的属性连线被前者重写
  3. 注解连线在默认情况下在Spring容器中不打卡,因此,在可以使用基于注解的连线之前,可以在 Spring 配置文件中启用它,在 Spring 应用程序中使用的任何注解可以到下面的配置文件中。
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    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">

   <context:annotation-config/>
   <!-- bean definitions go here -->

</beans>
  1. 一旦配置了后,就可以开始注解代码,表明spring应该自动连接值到属性,方法和构造函数
  2. 比较重要的注解有
    1. @Required 注解应用于 bean 属性的 setter 方法。
    2. @Autowired 注解可以应用到 bean 属性的 setter 方法,非 setter 方法,构造函数和属性。
    3. @Qualifier通过指定确切的将被连线的 bean,@Autowired 和 @Qualifier 注解可以用来删除混乱。
    4. Spring 支持 JSR-250 的基础的注解,其中包括了 @Resource,@PostConstruct 和 @PreDestroy 注解。

Spring @Required 注解

  1. @Required 注解应用于 bean 属性的 setter 方法,表明受到影响的bean属性在配置时必须放在XML配置文件中,否则容器就会抛出一个 BeanInitializationException 异常

Spring @Required 注解样例

  1. 创建一个名为 SpringExample 的项目,并且在所创建项目的 src 文件夹下创建一个名为 com.tutorialspoint 的包。
  2. 使用 Add External JARs 选项添加所需的 Spring 库文件
  3. 在 com.tutorialspoint 包下创建 Java 类 Student 和 MainApp
  4. 在 src 文件夹下创建 Beans 配置文件 Beans.xml。

Student.java 文件的内容:

package com.tutorialspoint;
import org.springframework.beans.factory.annotation.Required;
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;
   }
}

MainApp.java 文件的内容:

package com.tutorialspoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
      Student student = (Student) context.getBean("student");
      System.out.println("Name : " + student.getName() );
      System.out.println("Age : " + student.getAge() );
   }
}

配置文件 Beans.xml: 文件的内容:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    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">

   <context:annotation-config/>

   <!-- Definition for student bean -->
   <bean id="student" class="com.tutorialspoint.Student">
      <property name="name"  value="Zara" />

      <!-- try without passing age and check the result -->
      <!-- property name="age"  value="11"-->
   </bean>

</beans>

运行一下应用程序,一切都正常的话,这将引起 BeanInitializationException 异常,并且会输出一下错误信息和其他日志消息

Property 'age' is required for bean 'student'

从 “age” 属性中删除了注解后

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    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">

   <context:annotation-config/>

   <!-- Definition for student bean -->
   <bean id="student" class="com.tutorialspoint.Student">
      <property name="name"  value="Zara" />
      <property name="age"  value="11"/>
   </bean>

</beans>

Spring @Autowired 注解

  1. 使用 Spring 开发时,进行配置主要有两种方式,一是 xml 的方式,二是 java config 的方式
  2. java config 用的比较多了,在使用 java config 的过程当中,我们不可避免的会有各种各样的注解打交道
  3. 使用最多的注解应该就是 @Autowired 注解了。这个注解的功能就是为我们注入一个定义好的 bean。

@Autowired 注解的作用到底是什么

  1. @Autowired 这个注解属于 Spring 的容器配置的一个注解,
  2. 与它同属容器配置的注解还有:@Required,@Primary, @Qualifier 等等。因此 @Autowired 注解是一个用于容器 ( container ) 配置的注解。
  3. autowire,这个单词的意思是自动装配的意思,在 Spring中,自动装配指的就是使用将 Spring 容器中的 bean 自动的和我们需要这个 bean 的类组装在一起。

@Autowired 注解的用法

  1. @Autowired 注解应用于构造函数,如以下示例所示
public class MovieRecommender {
 
    private final CustomerPreferenceDao customerPreferenceDao;
 
    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }
 
    // ...
}
  1. 将 @Autowired 注解应用于 setter 方法
public class SimpleMovieLister {
 
    private MovieFinder movieFinder;
 
    @Autowired
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
 
    // ...
}
  1. 将 @Autowired 注解应用于具有任意名称和多个参数的方法
public class MovieRecommender {
 
    private MovieCatalog movieCatalog;
 
    private CustomerPreferenceDao customerPreferenceDao;
 
    @Autowired
    public void prepare(MovieCatalog movieCatalog,
            CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }
 
    // ...
}
  1. 也可以将 @Autowired 注解应用于字段,或者将其与构造函数混合
public class MovieRecommender {
 
    private final CustomerPreferenceDao customerPreferenceDao;
 
    @Autowired
    private MovieCatalog movieCatalog;
 
    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }
 
    // ...
}
  1. 直接应用于字段是我们使用的最多的一种方式,但是使用构造方法注入从代码层面却是更加好的
  2. 将 @Autowired 注解添加到需要该类型数组的字段或方法,则 Spring 会从 ApplicationContext 中搜寻符合指定类型的所有 bean
public class MovieRecommender {
 
    @Autowired
    private MovieCatalog[] movieCatalogs;
 
    // ...
}
  1. 将 @Autowired 注解添加到需要的容器,下面是 set 以及 map 的例子
public class MovieRecommender {
 
    private Set<MovieCatalog> movieCatalogs;
 
    @Autowired
    public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
        this.movieCatalogs = movieCatalogs;
    }
 
    // ...
}
public class MovieRecommender {
 
    private Map<String, MovieCatalog> movieCatalogs;
 
    @Autowired
    public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
        this.movieCatalogs = movieCatalogs;
    }
 
    // ...
}

Spring @Qualifier 注解

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

Spring @Qualifier 注解样例

  1. 创建一个名为 SpringExample 的项目,并且在所创建项目的 src 文件夹下创建一个名为 com.tutorialspoint 的包
  2. 使用 Add External JARs 选项添加所需的 Spring 库文件
  3. 在 com.tutorialspoint 包下创建 Java 类 Student,Profile 和 MainApp。
  4. 在 src 文件夹下创建 Beans 配置文件 Beans.xml。

Student.java 文件的内容:

package com.tutorialspoint;
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;
   }
}

Profile.java 文件的内容:

package com.tutorialspoint;
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() );
   }
}

MainApp.java 文件的内容

package com.tutorialspoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
      Profile profile = (Profile) context.getBean("profile");
      profile.printAge();
      profile.printName();
   }
}

配置文件 Beans.xml 的示例

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    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">

   <context:annotation-config/>

   <!-- Definition for profile bean -->
   <bean id="profile" class="com.tutorialspoint.Profile">
   </bean>

   <!-- Definition for student1 bean -->
   <bean id="student1" class="com.tutorialspoint.Student">
      <property name="name"  value="Zara" />
      <property name="age"  value="11"/>
   </bean>

   <!-- Definition for student2 bean -->
   <bean id="student2" class="com.tutorialspoint.Student">
      <property name="name"  value="Nuha" />
      <property name="age"  value="2"/>
   </bean>

</beans>

Spring JSR-250 注释

  1. 基于 JSR-250 注释,它包括 @PostConstruct, @PreDestroy 和 @Resource 注释。尽管这些注释并不是真正所需要
  2. 可以使用 @PostConstruct 注释作为初始化回调函数的一个替代
  3. @PreDestroy 注释作为销毁回调函数的一个替代,

Spring JSR-250 注释样例

  1. 创建一个名为 SpringExample 的项目,并且在所创建项目的 src 文件夹下创建一个名为 com.tutorialspoint 的包。
  2. 使用 Add External JARs 选项添加所需的 Spring 库文件
  3. 在 com.tutorialspoint 包下创建 Java 类 HelloWorld 和 MainApp。
  4. 在 src 文件夹下创建 Beans 配置文件 Beans.xml。

HelloWorld.java 文件的内容:

package com.tutorialspoint;
import javax.annotation.*;
public class HelloWorld {
   private String message;
   public void setMessage(String message){
      this.message  = message;
   }
   public String getMessage(){
      System.out.println("Your Message : " + message);
      return message;
   }
   @PostConstruct
   public void init(){
      System.out.println("Bean is going through init.");
   }
   @PreDestroy
   public void destroy(){
      System.out.println("Bean will destroy now.");
   }
}

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

package com.tutorialspoint;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
   public static void main(String[] args) {
      AbstractApplicationContext context = 
                          new ClassPathXmlApplicationContext("Beans.xml");
      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
      obj.getMessage();
      context.registerShutdownHook();
   }
}

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

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    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">

   <context:annotation-config/>

   <bean id="helloWorld" 
       class="com.tutorialspoint.HelloWorld"
       init-method="init" destroy-method="destroy">
       <property name="message" value="Hello World!"/>
   </bean>

</beans>

运行应用程序输出

Bean is going through init.
Your Message : Hello World!
Bean will destroy now.

Spring @Resource 注释:

  1. 可以在字段中或者 setter 方法中使用 @Resource 注释,它和在 Java EE 5 中的运作是一样的
  2. @Resource 注释使用一个 ‘name’ 属性,该属性以一个 bean 名称的形式被注入遵循 by-name 自动连接语义
package com.tutorialspoint;
import javax.annotation.Resource;
public class TextEditor {
   private SpellChecker spellChecker;
   @Resource(name= "spellChecker")
   public void setSpellChecker( SpellChecker spellChecker ){
      this.spellChecker = spellChecker;
   }
   public SpellChecker getSpellChecker(){
      return spellChecker;
   }
   public void spellCheck(){
      spellChecker.checkSpelling();
   }
}
  1. 默认名称源于字段名或者 setter 方法,在字段的情况下,它使用的是字段名;在一个 setter 方法情况下,它使用的是 bean 属性名称。

Spring 基于Java的配置

  1. 基于 Java 的配置选项,可以在不用配置 XML 的情况下编写大多数的 Spring,但是一些有帮助的基于 Java 的注解
  2. @Configuration 和 @Bean 注解
    1. 带有 @Configuration 的注解类表示这个类可以使用 Spring IoC 容器作为 bean 定义的来源
    2. @Bean 注解告诉 Spring,一个带有 @Bean 的注解方法将返回一个对象,该对象应该被注册为在 Spring 应用程序上下文中的 bean
  3. 最简单可行的 @Configuration 类如下所示
package com.tutorialspoint;
import org.springframework.context.annotation.*;
@Configuration
public class HelloWorldConfig {
   @Bean 
   public HelloWorld helloWorld(){
      return new HelloWorld();
   }
}

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

<beans>
   <bean id="helloWorld" class="com.tutorialspoint.HelloWorld" />
</beans>
  1. 在这里,带有 @Bean 注解的方法名称作为 bean 的 ID,它创建并返回实际的 bean,配置类可以声明多个 @Bean。一旦定义了配置类可以使用 AnnotationConfigApplicationContext 来加载并把他们提供给 Spring 容器
public static void main(String[] args) {
   ApplicationContext ctx = 
   new AnnotationConfigApplicationContext(HelloWorldConfig.class); 
   HelloWorld helloWorld = ctx.getBean(HelloWorld.class);
   helloWorld.setMessage("Hello World!");
   helloWorld.getMessage();
}

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

public static void main(String[] args) {
   AnnotationConfigApplicationContext ctx = 
   new AnnotationConfigApplicationContext();
   ctx.register(AppConfig.class, OtherConfig.class);
   ctx.register(AdditionalConfig.class);
   ctx.refresh();
   MyService myService = ctx.getBean(MyService.class);
   myService.doStuff();
}

Spring 基于Java的配置样例

  1. 创建一个名称为 SpringExample 的项目,并且在创建项目的 src 文件夹中创建一个包 com.tutorialspoint
  2. 使用 Add External JARs 选项,添加所需的 Spring 库,
  3. 使用基于 java 的注解,所以还需要添加来自 Java 安装目录的 CGLIB.jar 和可以从 asm.ow2.org 中下载的 ASM.jar 库。
  4. 在 com.tutorialspoint 包中创建 Java 类 HelloWorldConfig、HelloWorld 和 MainApp。
  5. 最后一步是创建的所有 Java 文件和 Bean 配置文件的内容,并运行应用程序

** HelloWorldConfig.java 文件的内容**

package com.tutorialspoint;
import org.springframework.context.annotation.*;
@Configuration
public class HelloWorldConfig {
   @Bean 
   public HelloWorld helloWorld(){
      return new HelloWorld();
   }
}

HelloWorld.java 文件的内容:

package com.tutorialspoint;

public class HelloWorld {
   private String message;

   public void setMessage(String message){
      this.message  = message;
   }

   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
}

MainApp.java 文件的内容:

package com.tutorialspoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.*;

public class MainApp {
   public static void main(String[] args) {
      ApplicationContext ctx = 
      new AnnotationConfigApplicationContext(HelloWorldConfig.class);

      HelloWorld helloWorld = ctx.getBean(HelloWorld.class);

      helloWorld.setMessage("Hello World!");
      helloWorld.getMessage();
   }
}

Spring 基于Java的配置 -注入Bean的依赖性

  1. 当 @Beans 依赖对方时,表达这种依赖性非常简单,只要有一个 bean 方法调用另一个,
package com.tutorialspoint;
import org.springframework.context.annotation.*;
@Configuration
public class AppConfig 初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段

初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段

Spring总结七:AOP动态代理的实现

Spring boot:thymeleaf 没有正确渲染片段

What's the difference between @Component, @Repository & @Service annotations in Spring?(代码片段

spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象(代码片段