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框架当中用到的常用的注解就讲解完毕了。如有在看到新的注解内容,可能会继续更新此贴。

 

posted @ 2017-03-29 16:34  Wellhold  阅读(3999)  评论(0编辑  收藏  举报