Spring使用注解配置依赖注入

大部分情况下,使用Spring配置依赖注入时,都是使用注解来进行配置,因为注解比xml要方便和简单。不过类似于数据源对象这种配置信息容易变更的对象除外,这种对象使用xml文件来进行配置会更适合,方便于在外部进行修改,而不需要打开代码来进行修改。

接下来简单介绍一下注解的配置方式,首先要让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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       ">

    <!-- 让spring支持注解 -->
    <context:annotation-config/>
    <!-- 指定哪些包下的类受可以让Spring通过注解来管理 -->
    <context:component-scan base-package="org.zero01"/>

</beans>

通过注解配置来让Spring帮我们创建对象,Student类代码如下:

package org.zero01;

import org.springframework.stereotype.Component;

// 加上这个注解表示该类受到Spring的管理,注解的值为该类的id,该注解的作用相当于xml中的bean标签
@Component("stu")
public class Student {
        ...

测试代码:

package org.zero01;

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

public class Test {

    public static void main(String[] args) {

        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");

        // 同样的通过配置的id获得实例对象
        Student stu1 = (Student) app.getBean("stu");
        Student stu2 = (Student) app.getBean("stu");

        // 默认都是单例对象
        if (stu1 == stu2) {
            System.out.println("单例对象");
        }else{
            System.out.println("非单例对象");
        }
    }
}

运行结果:

单例对象

使用注解时可以不配置id值,直接写上 @Component 也行:

package org.zero01;

import org.springframework.stereotype.Component;

@Component
public class Student {
        ...

然后通过该类的class来获取实例对象:

Student stu1 = app.getBean(Student.class);

但是这种方式的灵活性没有使用id值的方式好,因为字符串是可以通过变量改变的,而这种使用class的方式相当于是写死在代码上了。

如果不希望从容器里取出来的不是单例对象的话,可以使用 @Scope 注解来配置指定使用原型模式,需要配置属性的值可以使用 @Value 注解进行配置,例如:

package org.zero01;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.context.annotation.Scope;

@Component("stu")
@Scope(value = "prototype") // 取值与xml中的scope属性是一样的
public class Student {

    @Value("小明")
    private String name;
    @Value("15")
    private int age;
    @Value("南京")
    private String address;
    ...

测试代码:

package org.zero01;

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

public class Test {

    public static void main(String[] args) {

        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");

        Student stu1 = app.getBean(Student.class);
        Student stu2 = app.getBean(Student.class);

        if (stu1 == stu2) {
            System.out.println("单例对象");
        }else{
            System.out.println("非单例对象");
        }

        System.out.println(stu1.getName());
        System.out.println(stu1.getAge());
        System.out.println(stu1.getAddress());
    }
}

运行结果:

非单例对象
小明
15
南京

注:我们可以将 @Value 注解写在属性的setter方法上,和写在属性上的作用是一样的。

如果需要注入自建类型,有两个注解可以做到,分别是 @Resource 和 @Autowired,但是要想通过这两个注解来配置依赖注入,被注入的对象需要写上 @Component 注解:

package org.zero01;

import org.springframework.stereotype.Component;

@Component("phone")
public class Phone {
}

package org.zero01;

import org.springframework.stereotype.Component;

@Component("dog")
public class Dog {
}

然后才可以使用 @Resource 和 @Autowired 注解配置依赖注入,Student类代码:

package org.zero01;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.context.annotation.Scope;

import javax.annotation.Resource;

@Component("stu")
@Scope(value = "prototype")
public class Student {

    @Value("小明")
    private String name;
    @Value("15")
    private int age;
    @Value("南京")
    private String address;
    @Resource
    private Dog dog;
    @Autowired
    private Phone phone;
    ...

测试代码:

package org.zero01;

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

public class Test {

    public static void main(String[] args) {

        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");

        Student stu1 = app.getBean(Student.class);

        System.out.println(stu1.getName());
        System.out.println(stu1.getAge());
        System.out.println(stu1.getAddress());
        System.out.println(stu1.getDog());
        System.out.println(stu1.getPhone());
    }
}

运行结果:

小明
15
南京
[email protected]
[email protected]

@Autowired 和 @Resource的区别简述:

  • 用途:做bean的注入时使用
  • 历史:@Autowired 属于Spring的注解,@Resource 不属于Spring的注解,是JDK1.6支持的注解
  • 共同点:装配bean. 写在字段上,或写在setter方法
  • 不同点:
    • @Autowired 默认按类型装配,依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,例如:@Autowired(required=false),也可以使用名称装配,配合 @Qualifier 注解。
    • @Resource 是JDK1.6支持的注解,默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名,按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
  • 便利程度:两者的便利程度都差不多,都可以实现自动装配
  • 耦合问题:可能会有人说使用Java自带的 @Resource 可以降低与Spring的耦合,但实际上注解处理器我们使用的是Spring提供的,是一样的,无所谓解耦不解耦的说法


使用以上介绍到的注解做一个简单的增删查改小例题:

pom.xml文件配置如下:

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.14.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.39</version>
        </dependency>
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20160810</version>
        </dependency>
    </dependencies>

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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       ">

    <!-- 让spring支持注解 -->
    <context:annotation-config/>
    <!-- 指定哪些包下的类受可以让Spring通过注解来管理 -->
    <context:component-scan base-package="org.zero01"/>

    <!-- 配置数据源对象 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
          p:driverClass="com.mysql.jdbc.Driver"
          p:jdbcUrl="jdbc:mysql:///school"
          p:user="root"
          p:password="your_password"
          p:maxPoolSize="10"
          p:minPoolSize="1"
          p:loginTimeout="2000"
    />

</beans>

首先是接口代码:

package org.zero01.dao;

import org.zero01.pojo.Student;

import java.util.List;

public interface DAO {

    public int insert(Student student) throws Exception;
    public int delete(int sid) throws Exception;
    public List<Student> selectAll() throws Exception;
    public int update(Student student) throws Exception;
}

package org.zero01.service;

import org.zero01.pojo.Student;

import java.util.List;

public interface Service {

    public int enterSchool(Student student);
    public int dropOut(int sid);
    public List<Student> getStudents();
    public int updateData(Student student);

}

package org.zero01.view;

import org.zero01.pojo.Student;

import java.util.List;

public interface View {

    public int enterSchool(Student student);
    public int dropOut(int sid);
    public List<Student> getStudents();
    public int updateData(Student student);
}

然后是具体的实现类代码,StudentDAO类:

package org.zero01.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.zero01.pojo.Student;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

@Component("stuDAO")
public class StudentDAO implements DAO {

    @Autowired
    private DataSource dataSource;

    public int insert(Student student) throws Exception {

        Connection connection = null;

        try {

            connection = dataSource.getConnection();
            String sql = "INSERT INTO student(sname,age,sex,address) VALUES (?,?,?,?)";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, student.getSname());
            preparedStatement.setInt(2, student.getAge());
            preparedStatement.setString(3, student.getSex());
            preparedStatement.setString(4, student.getAddress());

            int row = preparedStatement.executeUpdate();

            if (row > 0) {
                return row;
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            connection.close();
        }

        return 0;
    }

    public int delete(int sid) throws Exception {

        Connection connection = null;

        try {

            connection = dataSource.getConnection();
            String sql = "DELETE FROM student WHERE sid=?";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1, sid);

            int row = preparedStatement.executeUpdate();

            if (row > 0) {
                return row;
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            connection.close();
        }

        return 0;
    }

    public List<Student> selectAll() throws Exception {
        Connection connection = null;

        try {

            connection = dataSource.getConnection();
            String sql = "select * from student";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);

            ResultSet resultSet = preparedStatement.executeQuery();

            List<Student> students = new ArrayList<Student>();
            while (resultSet.next()) {
                Student student = new Student();
                student.setSid(resultSet.getInt("sid"));
                student.setSname(resultSet.getString("sname"));
                student.setSex(resultSet.getString("sex"));
                student.setAddress(resultSet.getString("address"));
                students.add(student);
            }
            return students;

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            connection.close();
        }

        return null;
    }

    public int update(Student student) throws Exception {
        Connection connection = null;

        try {

            connection = dataSource.getConnection();
            String sql = "UPDATE student SET sname=?,age=?,sex=?,address=? WHERE sid=?";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, student.getSname());
            preparedStatement.setInt(2, student.getAge());
            preparedStatement.setString(3, student.getSex());
            preparedStatement.setString(4, student.getAddress());
            preparedStatement.setInt(5, student.getSid());

            int row = preparedStatement.executeUpdate();

            if (row > 0) {
                return row;
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            connection.close();
        }

        return 0;
    }
}

SchoolService代码:

package org.zero01.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.zero01.dao.DAO;
import org.zero01.pojo.Student;

import java.util.List;

@Component("schoolService")
public class SchoolService implements Service {

    @Autowired
    private DAO dao;

    public int enterSchool(Student student) {
        try {
            return dao.insert(student);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    public int dropOut(int sid) {
        try {
            return dao.delete(sid);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    public List<Student> getStudents() {
        try {
            return dao.selectAll();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public int updateData(Student student) {
        try {
            return dao.update(student);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }
}

SchoolAction代码:

package org.zero01.view;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.zero01.pojo.Student;
import org.zero01.service.Service;

import java.util.List;

@Component("stuAction")
public class SchoolAction implements View {

    @Autowired
    private Service schoolService;

    public int enterSchool(Student student) {
        return schoolService.enterSchool(student);
    }

    public int dropOut(int sid) {
        return schoolService.dropOut(sid);
    }

    public List<Student> getStudents() {
        return schoolService.getStudents();
    }

    public int updateData(Student student) {
        return schoolService.updateData(student);
    }
}

从以上的代码可以看到,我们没有在哪一个类里写了关于任何实例化对象的代码,而是把实例化这项工作交给Spring容器去帮我们完成,这样每个类都不需要去管理、维护自己的依赖对象,只需要完成自己业务代码即可,这样弱化了类与类之间的依赖,让代码的复杂度降低,每个类都只需要维护自己的业务代码即可,这是Spring的IOC模块给我们带来的好处。而且每个类都依赖的是接口,而不是具体的实现类,符合依赖倒转原则,不会导致代码紧耦合,当具体的实现类被替换时,不会影响到其他类。

测试代码:

package org.zero01;

import org.json.JSONObject;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.zero01.view.View;
import org.zero01.pojo.Student;

import java.util.HashMap;
import java.util.Map;

public class Test {

    public static void main(String[] args) {

        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");

        View view = (View) app.getBean("stuAction");
        Student student = (Student) app.getBean("student");

        System.out.println("enterSchool() 影响行数:" + view.enterSchool(student));
        System.out.println("dropOut() 影响行数:" + view.dropOut(25));

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("studentList", view.getStudents());
        map.put("length", view.getStudents().size());
        System.out.println(new JSONObject(map));

        student.setSname("小刚");
        student.setAddress("长沙");
        student.setAge(18);
        student.setSid(29);
        System.out.println("updateData() 影响行数:" + view.updateData(student));
    }
}

运行结果:

enterSchool() 影响行数:1
dropOut() 影响行数:1
{
  "studentList": [
    {
      "address": "南京",
      "sname": "小明",
      "sex": "男",
      "age": 0,
      "sid": 26
    },
    {
      "address": "南京",
      "sname": "小明",
      "sex": "男",
      "age": 0,
      "sid": 27
    },
    {
      "address": "南京",
      "sname": "小明",
      "sex": "男",
      "age": 0,
      "sid": 28
    },
    {
      "address": "南京",
      "sname": "小明",
      "sex": "男",
      "age": 0,
      "sid": 29
    },
    {
      "address": "南京",
      "sname": "小明",
      "sex": "男",
      "age": 0,
      "sid": 30
    },
    {
      "address": "南京",
      "sname": "小明",
      "sex": "男",
      "age": 0,
      "sid": 31
    }
  ],
  "length": 6
}
updateData() 影响行数:1

原文地址:http://blog.51cto.com/zero01/2074096

时间: 2024-10-07 23:21:09

Spring使用注解配置依赖注入的相关文章

spring下应用@Resource, @Autowired 和 @Inject注解进行依赖注入的差

代码: 为了探寻  '@Resource', '@Autowired', 和'@Inject'如何解决依赖注入中的问题,我创建了一个"Party"接口,和它的两个实现类"Person","Organization".这样我就可以在注入Bean的时候不必使用具体类型(指使用接口类型即可).这样做也方便我研究当一个接口有多个实现类与之匹配的时候Spring是如何解决依赖注入的不确定性的. public interface Party {} packa

Spring学习一(依赖注入/Bean/注解等)

1.Spring依赖注入的方式. 2.依赖注入的类型 3.Bean的作用域 4.自动注入 5.使用注解的方式 6.在spring配置文件中引入属性文件 1.Spring依赖注入的方式 平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中.依赖注入的另一种说法是“

Spring quartz Job不能依赖注入,Spring整合quartz Job任务不能注入

Spring quartz Job不能依赖注入,Spring整合quartz Job任务不能注入 Spring4整合quartz2.2.3中Job任务使用@Autowired不能注入 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ©Copyright 蕃薯耀 2017年9月6日 http://ww

回客科技 面试的 实现ioc 容器用到的技术,简述BeanFactory的实现原理,大搜车面试的 spring 怎么实现的依赖注入(DI)

前言:这几天的面试,感觉自己对spring 的整个掌握还是很薄弱.所以需要继续加强. 这里说明一下spring的这几个面试题,但是实际的感觉还是不对的,这种问题我认为需要真正读了spring的源码后说出来的东西才有意义.这种面试的问法,也只能是面试的问法,对实际的掌握还是没有丝毫意义的.所以我认为 有机会一定要读下spring的源码 来过一遍 具体实现,这样的才是有意义的做法.同意的请举手. 这里说明一下这三个spring 面试问题: 1.回客科技 面试的 实现ioc 容器用到的技术 第1种 说

采用Spring管理Bean和依赖注入

1.实例化spring容器 和 从容器获取Bean目标 实例化Spring容器常用的两种办法: 办法一: 在类途径下寻觅配置文件来实例化容器 [引荐运用] ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"beans.xml"}); 办法二: 在文件体系途径下寻觅配置文件来实例化容器 [这种办法能够在开发期间运用] ApplicationContext ctx = new FileSyst

Spring MVC注解配置结合Hibernate的入门教程及其代码实例

原文:Spring MVC注解配置结合Hibernate的入门教程及其代码实例 源代码下载地址:http://www.zuidaima.com/share/1787210045197312.htm 1.概述 本文旨在搭建Spring MVC+Hibernate开发框架,通过一个简单的demo讲解Spring MVC的相关配置文件,以及通过注解方式实现简单功能. 开发框架:Spring+Spring MVC+Hibernate(Spring所用的版本为3.0.5). 数据库:MySQL(数据库名称

(转)Spring读书笔记-----Spring核心机制:依赖注入

Java应用(从applets的小范围到全套n层服务端企业应用)是一种典型的依赖型应用,它就是由一些互相适当地协作的对象构成的.因此,我们说这些对象间存在依赖关系.加入A组件调用了B组件的方法,我们就可以称A组件依赖于B组件.我们通过使用依赖注入,Java EE应用中的各种组件不需要以硬编码方式耦合在一起,甚至无需使用工厂模式.当某个Java 实例需要其他Java 实例时,系统自动提供所需要的实例,无需程序显示获取,这种自动提供java实例我们谓之为依赖注入,也可以称之为控制反转(Inversi

Spring-Context的注解实现依赖注入功能

使用Spring-Context的注解实现依赖注入功能. Demo要点: 本例子中主要使用Annotation功能来实现对MoviceService的注入.我们将Cinema.java的头部标注为@Component说明该类交由Spring托管.而Cinema.java中的属性MoviceService标注为@Autowired,则Spring在初始化Cinema类时会从Application Context中找到类型为MovieService的Bean,并赋值给Cinema.在Applicat

spring使用注解通过子类注入父类的私有变量

方法一 通过 super.setBaseDao方法设置父类私有变量 父类 public class BaseServiceImpl {    private BaseDao baseDao; public BaseDao getBaseDao() {        return baseDao;    } public void setBaseDao(BaseDao baseDao) {        this.baseDao = baseDao;    } public void test()