Spring:基於注解的依賴注入的使用


1.什么是pojo?什么是bean?

首先,在之前幾篇Spring的介紹文章當中,自己都提到了一個名詞叫做POJO類,但是在回顧Spring的注解的使用的時候,去形容java當中的對象還有一個名詞是叫做Bean,那么究竟Pojo類和Bean之間有什么區別呢?本人特地為此進行了資料收集,總結如下:

什么是POJO類呢?所謂的POJO,即Plain old java object,翻譯過來是純凈的java老式的對象,POJO的內在含義是指那些沒有從任何類繼承、也沒有實現任何接口,更沒有被其它框架侵入的java對象,pojo一般是用於數據的臨時傳遞,它只能裝載數據, 作為數據存儲的載體,而不具有業務邏輯處理的能力,常常在dao層的實現的時候需要POJO類。

而什么是JAVAbean呢?所謂的JAVAbean是一種JAVA語言寫成的可重用組件。它的方法命名,構造及行為必須符合特定的約定:

  1. 這個類必須有一個公共的缺省構造函數。
  2. 這個類的屬性使用getter和setter來訪問,其他方法遵從標准命名規范。
  3. 這個類應是可序列化的。 
因為這些要求主要是靠約定而不是靠實現接口,所以許多開發者把JavaBean看作遵從特定命名約定的POJO類。簡而言之,當一個Pojo可序列化,有一個無參的構造函數,使用getter和setter方法來訪問屬性時,他就是一個JavaBean。
 
2.通過注解的方式去運用Spring
 
明確了POJO類和JAVAbean的概念之后,我們接下來回顧一下Spring當中的依賴注入的方式,前頭我們所說記錄的是,是Spring當中的對象的屬性注入的方式,那么在Spring當中,如何向對象注入所需要依賴的對象呢?在使用配置文件的時候,我們通常都是通過Spring的上下文,即ApplicationContext的實例當中的getBean方法從SpringIOC容器當中去獲取到依賴對象的實例,代碼如下:
 
package bjtu.wellhold.testSpring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class testUnit {

    public static void main(String[] args) {

        ApplicationContext cfg = new ClassPathXmlApplicationContext("Config.xml");
        Person person = cfg.getBean("person", Person.class);
        System.out.println(person);

    }
}

從代碼看出,通過ApplicationContext的實例cfg當中的getBean方法,從Spring容器當中獲取到了Person類的實例person(之前已經在配置文件當中配置好person,如有不會,請翻看之前的文章)之后再對獲取到的person實例進行其他的邏輯操作。這是我們之前使用的基於配置文件的情況下的對象依賴注入的方式,可以看到這種方式還是比較繁瑣的,因為要獲取到Spring容器當中的實例之前,我們首先要獲取到Spring上下文的實例,才能通過getBean的方法去獲取到IOC容器當中的實例,在一點在Spring3.0之后,提出了一種更為簡便,更為優雅的方式去實現了包括將pojo或bean類注冊到Spring的容器當中,或者從Spring容器當中去獲取到相應的實例的方式,那就是通過注解的形式。

首先回顧Spring的使用過程,我們第一步要先了解通過注解的形式,如何將我們所編寫的Pojo類或者JAVAbean注冊到Spring當中讓其去管理,這時候我們使用的注解是@Component,通過這個注解可以講所定義的JAVAbean或POJO類注冊到Spring容器當中,並且根據所涉及的JAVAbean所處的層不同,還可以將@Component特化成一下幾個注解:@Repository,用於DAO層,通常用於標記pojo類;@Service,用於業務邏輯層,通常用來標記JAVAbean,@Controller,用於控制表示層,通常也是用於標記JAVAbean的。使用方式也幾乎一致,以下舉一個@Repository的例子:

package bjtu.wellhold.testSpring;

import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

@Repository("person")
public class Person {

    private String name;  
    private int age;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }  
 

    
}

在代碼中,@Repository括號中的內容指的是將這個類交付與Spring容器之后,在Spring容器當中,這個類的實例的名稱,以上注解等同於在配置文件當中編寫:

<bean id="person" class="bjtu.wellhold.testSpring.Person"></bean>

 

在了解了如何將編寫的POJO類和JAVAbean類注冊到容器當中之后,我們再來看看如何從容器當中通過注解的方式去獲取到這些類的實例,我們通過的是@Resource這個注解去進行。我們首先寫一個PersonFactory類,通過注解的形式將Person的實例注入到PersonFactory當中:

package bjtu.wellhold.testSpring;

import javax.annotation.Resource;

import org.springframework.stereotype.Repository;

@Repository("personFactory")
public class PersonFactory {


    @Resource(name="person",type=Person.class) private Person person;
    
    public Person createPerson() 
    {
        System.out.println(person.toString());
        return person;
    }
    
}

從代碼可以看到。在被注入Person的實例的同時,PersonFactory也通過@Repository這個注解將自身托給了Spring容器去進行管理,之后我們來編寫程序入口:

package bjtu.wellhold.testSpring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

public class testUnit {

    public static void main(String[] args) {

        ApplicationContext cfg = new ClassPathXmlApplicationContext("Config.xml");
        Person person = cfg.getBean("person", Person.class);
        PersonFactory personfactory = cfg.getBean("personFactory", PersonFactory.class);
        personfactory.createPerson();

    }
}

簡單的解釋一下,為什么我們不在程序入口這里就直接通過注解注入Person的實例呢?而需要中間通過一個PersonFactory去驗證注入的效果?因為在程序的入口。main函數是一個靜態的方法,如果需要在main函數中注入Person的實例,則Person實例需要定義成靜態的,所謂的靜態的,即是在類加載的時候就需要實例化的,但在類加載的時候,main函數沒有被調用,並沒有執行Spring的上下文,所以這時候注入的Person實例一定會報空指針錯誤,即在未加載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:aop="http://www.springframework.org/schema/aop"  
    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/aop  
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
       http://www.springframework.org/schema/context  
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />   
    
    <context:annotation-config />
    
    <context:component-scan base-package="bjtu.wellhold.testSpring"/>

</beans>

以上就是@Component注解以及它的分支的使用方法。

之后我們在來了解另一個注解@Configuration的使用方法,顧名思義,是可以通過java類為提供Spring容器提供Bean定義的信息了,常常與@Bean注解進行使用,每個標注了@Bean的類方法都相當於提供了一個Bean的定義信息。為了驗證@Configuration,我們做兩個pojo類,一個名叫Person,一個名叫Mechine,並且將這兩個類注入到名叫Factory類當中,Factory類可以提供一個公共的方法打印這兩個類的實例的信息。代碼如下:

package bjtu.wellhold.testSpring;

import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

public class Person {

    private String name;  
    private int age;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }     
}
package bjtu.wellhold.testSpring;

public class Mechine {

    private int id;
    private String name;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    public String toString() {
        return "Mechine [id=" + id + ", name=" + name + "]";
    }
    
}
package bjtu.wellhold.testSpring;

import javax.annotation.Resource;

import org.springframework.stereotype.Repository;

public class Factory {

    private Person person;
    private Mechine mechine;
    
    public void returnPerson()
    {
        System.out.println(person);
    }
    
    public void returnMechine()
    {
        System.out.println(mechine);
    }
    
    public Person getPerson() {
        return person;
    }
    public void setPerson(Person person) {
        this.person = person;
    }
    public Mechine getMechine() {
        return mechine;
    }
    public void setMechine(Mechine mechine) {
        this.mechine = mechine;
    }

    @Override
    public String toString() {
        return "Factory [person=" + person + ", mechine=" + mechine + "]";
    }
    
}

之后我們通過一個FactoryConfiguration的類,進行@Configuration注解之后,為Spring提供Bean的配置信息,代碼如下:

package bjtu.wellhold.testSpring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FactoryConfiguration {
    
    @Bean
    public Person person(){
        return new Person();
    }
    
    @Bean
    public Mechine mechine()
    {
        Mechine mechine=new Mechine();
        mechine.setId(10);
        mechine.setName("wellhold");
        return mechine;
    }
    
    @Bean
    public Factory factory()
    {
        Factory factory=new Factory();
        factory.setMechine(mechine());
        factory.setPerson(person());
        return factory;
    }
    
}

其效果就如同在配置文件當中寫下如下內容

    <bean id="person" class="bjtu.wellhold.testSpring.Person"></bean>
    <bean id="mechine" class="bjtu.wellhold.testSpring.Mechine">
        <property name="id" value="10"/>
        <property name="name" value="wellhold"/>
    </bean>
    <bean id="factory" class="bjtu.wellhold.testSpring.Factory">
        <property name="person" ref="person"/>
        <property name="mechine" ref="mechine"/>
    </bean>

最后我們來看看我們的程序入口:

package bjtu.wellhold.testSpring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

public class testUnit {

    public static void main(String[] args) {

        ApplicationContext cfg = new ClassPathXmlApplicationContext("Config.xml");
        Factory factory = cfg.getBean("factory", Factory.class);
        factory.returnMechine();
        factory.returnPerson();
    }
}

到此,目前筆者了解到的Spring框架當中用到的常用的注解就講解完畢了。如有在看到新的注解內容,可能會繼續更新此貼。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM