Spring使用注解配置依赖注入
2018-02-28 23:24
441 查看
大部分情况下,使用Spring配置依赖注入时,都是使用注解来进行配置,因为注解比xml要方便和简单。不过类似于数据源对象这种配置信息容易变更的对象除外,这种对象使用xml文件来进行配置会更适合,方便于在外部进行修改,而不需要打开代码来进行修改。
接下来简单介绍一下注解的配置方式,首先要让Spring支持注解,编辑Spring配置文件内容如下:
通过注解配置来让Spring帮我们创建对象,Student类代码如下:
测试代码:
运行结果:
使用注解时可以不配置id值,直接写上 @Component 也行:
然后通过该类的class来获取实例对象:
但是这种方式的灵活性没有使用id值的方式好,因为字符串是可以通过变量改变的,而这种使用class的方式相当于是写死在代码上了。
如果不希望从容器里取出来的不是单例对象的话,可以使用 @Scope 注解来配置指定使用原型模式,需要配置属性的值可以使用 @Value 注解进行配置,例如:
测试代码:
运行结果:
注:我们可以将 @Value 注解写在属性的setter方法上,和写在属性上的作用是一样的。
如果需要注入自建类型,有两个注解可以做到,分别是 @Resource 和 @Autowired,但是要想通过这两个注解来配置依赖注入,被注入的对象需要写上 @Component 注解:
然后才可以使用 @Resource 和 @Autowired 注解配置依赖注入,Student类代码:
测试代码:
运行结果:
@Autowired 和 @Resource的区别简述:
用途:做bean的注入时使用
历史:@Autowired 属于Spring的注解,@Resource 不属于Spring的注解,是JDK1.6支持的注解
共同点:装配bean. 写在字段上,或写在setter方法
不同点:
@Autowired 默认按类型装配,依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,例如:
@Resource 是JDK1.6支持的注解,默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名,按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
便利程度:两者的便利程度都差不多,都可以实现自动装配
耦合问题:可能会有人说使用Java自带的 @Resource 可以降低与Spring的耦合,但实际上注解处理器我们使用的是Spring提供的,是一样的,无所谓解耦不解耦的说法
使用以上介绍到的注解做一个简单的增删查改小例题:
pom.xml文件配置如下:
Spring配置文件内容如下:
首先是接口代码:
然后是具体的实现类代码,StudentDAO类:
SchoolService代码:
SchoolAction代码:
从以上的代码可以看到,我们没有在哪一个类里写了关于任何实例化对象的代码,而是把实例化这项工作交给Spring容器去帮我们完成,这样每个类都不需要去管理、维护自己的依赖对象,只需要完成自己业务代码即可,这样弱化了类与类之间的依赖,让代码的复杂度降低,每个类都只需要维护自己的业务代码即可,这是Spring的IOC模块给我们带来的好处。而且每个类都依赖的是接口,而不是具体的实现类,符合依赖倒转原则,不会导致代码紧耦合,当具体的实现类被替换时,不会影响到其他类。
测试代码:
运行结果:
接下来简单介绍一下注解的配置方式,首先要让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 南京 org.zero01.Dog@47db50c5 org.zero01.Phone@5c072e3f
@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
相关文章推荐
- Spring 3.0 学习-DI 依赖注入_创建Spring 配置-使用一个或多个XML 文件作为配置文件,使用自动注入(byName),在代码中使用注解代替自动注入,使用自动扫描代替xml中bea
- spring 依赖注入注解配置原理解析
- Spring.net 控制反转(IOC)依赖注入(DI)的使用 以及Config文件的配置
- spring通过注解依赖注入和获取xml配置混合的方式
- spring 框架中的依赖注入(IOC--设值注入)---使用xml简单配置文件---的具体实例的简单实现
- Spring中依赖注入的使用和配置
- 零配置 之 12.2 注解实现Bean依赖注入 ——跟我学spring3
- Spring配置使用注解注入bean
- 使用Spring配置shiro时,自定义Realm中属性无法使用注解注入解决办法
- 原始方式:spring四种依赖注入方式 |注解方式:Spring零配置通过注解实现Bean依赖注入
- Spring零配置通过注解实现Bean依赖注入总结<转>
- spring 框架中的依赖注入(IOC--设值注入)--使用注解--的具体实例的简单实现
- 【第十二章】零配置 之 12.1 概述 12.2 注解实现Bean依赖注入 ——跟我学spring3
- spring-依赖注入的注解配置
- 使用Spring配置shiro时,自定义Realm中属性无法使用注解注入解决办法
- Spring使用注解的方式注入属性时的xml文件配置
- 开涛spring3(12.2) - 零配置 之 12.2 注解实现Bean依赖注入
- 使用dom4j:读取spring配置文件,实例化bean对象并注入依赖对象
- 【第十二章】零配置 之 12.2 注解实现Bean依赖注入 ——跟我学spring3
- 有关spring的依赖注入和@resource注解的使用