Spring框架进阶(二)

Spring依赖注入(DI)

依赖注入也是Spring框架的功能之一,其实在前面的一篇文章Spring框架入门(一)的例子中已经使用了功能,通过XML配置文件对category组件的name字段注入了value,除了基于设值函数的依赖注入,Spring还提供了基于构造函数的依赖注入。

构造函数的依赖注入

当容器调用带有一组参数的类构造函数时,基于构造函数的DI就完成了,其中每个参数代表一个对其他类的依赖。

新建School.java

package dependency.inject;

public class School {
	
	private Student student;
	
	public School(Student student) {
		// TODO Auto-generated constructor stub
		System.out.println("基于构造函数的依赖注入");
		this.student = student;
	}

	public Student getStudent() {
		return student;
	}

	public void setStudent(Student student) {
		this.student = student;
	}
	
	

}

新建Student.java

package dependency.inject;

public class Student {
	
	public Student() {
		// TODO Auto-generated constructor stub
		System.out.println("student1");
	}

}

在applicationContext.xml配置Bean

这里使用<constructor-arg ref="student"></constructor-arg>参数将student组件以构造函数的形式注入School类中

	<bean name="school" class="dependency.inject.School">
	<constructor-arg ref="student"></constructor-arg>
	</bean>
	
	<bean name="student" class="dependency.inject.Student"></bean>

接着只需在主类调用school组件即可

扫描二维码关注公众号,回复: 1908915 查看本文章
School school = (School)context.getBean("school");


Spring Beans自动装配

前面例子通过声明<constructor-arg>和<property>元素来注入。Spring也可以在不声明的情况下通过自动装配实现注入。

自动装配有三种模式,分别为

byName 由属性名自动装配
byType 由属性数据类型自动装配
constructor 适用于构造函数参数类型

byName

只需修改applicationContext.xml达到同样的效果

	<bean name="school" class="dependency.inject.School">
		<constructor-arg ref="student"></constructor-arg>
	</bean>

替换成

	<bean name="school" class="dependency.inject.School" autowire="byName">
	</bean>

byType

只需将byName修改成byType即可

	<bean name="school" class="dependency.inject.School" autowire="byType">
	</bean>


constructor

这种模式与byType类似,只不过应用于构造参数

将byType修改成constructor

	<bean name="school" class="dependency.inject.School" autowire="constructor">
	</bean>


Spring注解

Spring可以使用注解来配置依赖注入。只需在XML配置文件添加以下语句

<context:annotation-config/>

@Required注解

应用于bean属性的setter方法,表明受影响的bean属性在配置时必须放在XML配置中。

@Autowired注解

Setter方法中的@Autowired

它会在方法中试图执行byType自动连接

属性中的@Autowired

它可以代替setter方法,自动分配传递过来的值

构造函数中的@Autowired

当创建bean时,即使在XML文件中没有使用元素配置bean,构造函数也会被自动连接

@Qualifier注解

当创建多个相同类型的bean时,使用@Qualifier和@Autowired指定具体的bean以消除混乱。

@Resource注解

使用一个“name”属性以bean名称的形式注入,遵循byName自动连接语义


Spring AOP(面向切面编程)

在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能。

周边功能在Spring的面向切面编程AOP思想里,即被定义为切面

在面向切面编程AOP的思想里面,核心业务功能和切面功能分别独立进行开发,然后把切面功能和核心业务功能 "编织" 在一起,这就叫AOP。

在pom.xml引入spring-aspects依赖

		<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
			<version>5.0.6.RELEASE</version>
		</dependency>

创建ProductService类(核心业务功能类)

package aspect;

import org.springframework.stereotype.Component;

//AOP(Aspect Oriented Program)面向切面编程类
@Component("s")
public class ProductService {
	
	public void doSomeService() {
		System.out.println("doSomeService");
	}

}

创建LoggerAspect类(切面功能类)

在调用核心功能之前和之后分别打印日志

public class LoggerAspect {
	
	@Around(value = "execution(* ProductService.*(..))")
	public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out.println("strat log:" + joinPoint.getSignature().getName());
		Object object = joinPoint.proceed();	//执行目标方法
		System.out.println("end log:" + joinPoint.getSignature().getName());
		return object;
	}

}

在applicationContext.xml配置Bean和切面功能

	<bean name="s" class="aspect.ProductService"></bean>
	<bean id="loggerAspect" class="aspect.LoggerAspect"></bean>

	<!-- 配置切入点 -->
	<aop:config>
		<aop:aspect id="logAspect" ref="loggerAspect">
			<!-- 指定目标方法(核心功能) -->
			<aop:pointcut expression="execution(* aspect.ProductService.*(..))"
				id="loggerCutpoint" />
			<!-- 切入方法(辅助功能) -->
			<aop:around method="log" pointcut-ref="loggerCutpoint" />
		</aop:aspect>
	</aop:config>

在主类编写逻辑测试

        //面向切面编程(Aspect Oriented Program)
        ProductService service = (ProductService)context.getBean("s");
        service.doSomeService();

注解方式AOP

修改ProductService类

加上@Component("s")注解

@Component("s")	//表示这是一个bean,由Spring进行管理
public class ProductService {
	
	public void doSomeService() {
		System.out.println("doSomeService");
	}

}

修改LoggerAspect类

@Aspect	//表示这是一个切面
@Component	//表示这是一个bean,由Spring进行管理
public class LoggerAspect {
	
	@Around(value = "execution(* ProductService.*(..))")	//对这个类中的所有方法进行切面操作 
	public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out.println("strat log:" + joinPoint.getSignature().getName());
		Object object = joinPoint.proceed();	//执行目标方法
		System.out.println("end log:" + joinPoint.getSignature().getName());
		return object;
	}

}

修改applicationContext.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"
	xmlns:aop="http://www.springframework.org/schema/aop"
	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-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<!-- 开启组件扫描 -->
	<context:component-scan base-package="pojo"></context:component-scan>
	<context:component-scan base-package="aspect"></context:component-scan>
	<!-- 开启切面注解 -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

Spring JDBC

Spring JDBC 提供几种方法和数据库中相应的不同的类与接口,最受欢迎的还是JdbcTemplate。

JdbcTemplate 类

JdbcTemplate 类执行 SQL 查询、更新语句和存储过程调用,执行迭代结果集和提取返回参数值。

JdbcTemplate 类的实例是线程安全配置的。所以你可以配置 JdbcTemplate 的单个实例,然后将这个共享的引用安全地注入到多个 DAOs 中。

下面来实现简单的增删改查

创建数据库

create database spring;

创建表

CREATE TABLE Student(
   ID   INT NOT NULL AUTO_INCREMENT,
   NAME VARCHAR(20) NOT NULL,
   AGE  INT NOT NULL,
   PRIMARY KEY (ID)
);

在pom.xml引入spring-jdbc与mysql依赖

		<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.46</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>5.0.6.RELEASE</version>
		</dependency>

新建StudentDAO类(数据访问对象接口)

package jdbc;

import java.util.List;

import javax.sql.DataSource;

import dependency.inject.Student;

//数据访问对象
public interface StudentDAO {
	
	public void setDataSource(DataSource ds);

	public void create(String name, Integer age);

	public Student getStudent(Integer id);
	
	public List<Student> listStudents();
	
	public void delete(Integer id);

	public void update(Integer id, Integer age);

}

修改Student.java

package dependency.inject;

public class Student {

	private Integer age;
	private String name;
	private Integer id;

	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;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public Integer getId() {
		return id;
	}

}

新建StudentMapper类

实现RowMapper接口以映射列

package jdbc;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

import dependency.inject.Student;

//映射表的列
public class StudentMapper implements RowMapper<Student> {

	public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
		// TODO Auto-generated method stub
		Student student = new Student();
		student.setId(rs.getInt("id"));
		student.setName(rs.getString("name"));
		student.setAge(rs.getInt("age"));
		return student;
	}

}

新建StudentDAO类(数据操作类)

package jdbc;

import java.util.List;

import javax.sql.DataSource;

import org.springframework.jdbc.core.JdbcTemplate;

import dependency.inject.Student;

public class StudentJDBCTemplate implements StudentDAO {

	private DataSource dataSource;
	private JdbcTemplate jdbcTemplateObject;

	//设置数据源
	public void setDataSource(DataSource ds) {
		// TODO Auto-generated method stub
		this.dataSource = ds;
		this.jdbcTemplateObject = new JdbcTemplate(dataSource);
	}

	public void create(String name, Integer age) {
		String SQL = "insert into Student (name, age) values (?, ?)";
		jdbcTemplateObject.update(SQL, name, age);
		System.out.println("Created Record Name = " + name + " Age = " + age);
		return;
	}

	public Student getStudent(Integer id) {
		String SQL = "select * from Student where id = ?";
		Student student = jdbcTemplateObject.queryForObject(SQL, new Object[] { id }, new StudentMapper());
		return student;
	}

	public List<Student> listStudents() {
		String SQL = "select * from Student";
		List<Student> students = jdbcTemplateObject.query(SQL, new StudentMapper());
		return students;
	}

	public void delete(Integer id) {
		String SQL = "delete from Student where id = ?";
		jdbcTemplateObject.update(SQL, id);
		System.out.println("Deleted Record with ID = " + id);
		return;
	}

	public void update(Integer id, Integer age) {
		String SQL = "update Student set age = ? where id = ?";
		jdbcTemplateObject.update(SQL, age, id);
		System.out.println("Updated Record with ID = " + id);
		return;
	}

	public DataSource getDataSource() {
		return dataSource;
	}

	public JdbcTemplate getJdbcTemplateObject() {
		return jdbcTemplateObject;
	}

	public void setJdbcTemplateObject(JdbcTemplate jdbcTemplateObject) {
		this.jdbcTemplateObject = jdbcTemplateObject;
	}

}

修改applicationContext.xml文件

<!-- 配置数据源 -->
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost/spring?characterEncoding=utf8&useSSL=true" />
		<property name="username" value="root" />
		<property name="password" value="admin" />
	</bean>

	<bean id="studentJDBCTemplate" class="jdbc.StudentJDBCTemplate">
		<property name="dataSource" ref="dataSource" />

在主类编写逻辑测试

		// JDBC操作
		StudentJDBCTemplate studentJDBCTemplate = (StudentJDBCTemplate) context.getBean("studentJDBCTemplate");
		System.out.println("------Records Creation--------");
		studentJDBCTemplate.create("Zara", 11);
		studentJDBCTemplate.create("Nuha", 2);
		studentJDBCTemplate.create("Ayan", 15);
		System.out.println("------Listing Multiple Records--------");
		List<Student> students = studentJDBCTemplate.listStudents();
		for (Student record : students) {
			System.out.print("ID : " + record.getId());
			System.out.print(", Name : " + record.getName());
			System.out.println(", Age : " + record.getAge());
		}
		System.out.println("----Updating Record with ID = 2 -----");
		studentJDBCTemplate.update(2, 20);
		System.out.println("----Listing Record with ID = 2 -----");
		Student student = studentJDBCTemplate.getStudent(2);
		System.out.print("ID : " + student.getId());
		System.out.print(", Name : " + student.getName());
		System.out.println(", Age : " + student.getAge());

Spring事务管理

一个数据库事务是一个被视为单一的工作单元的操作序列。事务管理保证数据库操作要么完整地执行,要么完全不执行。以确保数据完整性和一致性。事务的概念可以描述为具有以下四个关键属性说成是 ACID:

原子性:事务应该当作一个单独单元的操作,这意味着整个序列操作要么是成功,要么是失败的。

一致性:这表示数据库的引用完整性的一致性,表中唯一的主键等。

隔离性:可能同时处理很多有相同的数据集的事务,每个事务应该与其他事务隔离,以防止数据损坏。

持久性:一个事务一旦完成全部操作后,这个事务的结果必须是永久性的,不能因系统故障而从数据库中删除。

Spring 支持两种类型的事务管理:

编程式事务管理 :这意味着你在编程的帮助下有管理事务。这给了你极大的灵活性,但却很难维护。

声明式事务管理 :这意味着你从业务代码中分离事务管理。你仅仅使用注释或 XML 配置来管理事务。

编程式事务管理

修改StudentJDBCTemplate类

public class StudentJDBCTemplate implements StudentDAO {
   private DataSource dataSource;
   private JdbcTemplate jdbcTemplateObject;
   private PlatformTransactionManager transactionManager;  //声明事务管理器
   public void setDataSource(DataSource dataSource) {
      this.dataSource = dataSource;
      this.jdbcTemplateObject = new JdbcTemplate(dataSource);
   }
   public void setTransactionManager(
      PlatformTransactionManager transactionManager) {
      this.transactionManager = transactionManager;
   }
   public void create(String name, Integer age, Integer marks, Integer year){
      TransactionDefinition def = new DefaultTransactionDefinition();    //定义默认事务
      TransactionStatus status = transactionManager.getTransaction(def);    //返回事务管理器状态码
      try {
         String SQL1 = "insert into Student (name, age) values (?, ?)";
         jdbcTemplateObject.update( SQL1, name, age);
         String SQL2 = "select max(id) from Student";
         int sid = jdbcTemplateObject.queryForInt( SQL2 );
         String SQL3 = "insert into Marks(sid, marks, year) " + 
                       "values (?, ?, ?)";
         jdbcTemplateObject.update( SQL3, sid, marks, year);
         System.out.println("Created Name = " + name + ", Age = " + age);
         transactionManager.commit(status);    //事务提交
      } catch (DataAccessException e) {
         System.out.println("Error in creating record, rolling back");
         transactionManager.rollback(status);    //异常回滚
         throw e;
      }
      return;

修改applicationContext.xml文件

   <!-- 配置事务管理器 -->
   <bean id="transactionManager" 
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource"  ref="dataSource" />    
   </bean>

   <bean id="studentJDBCTemplate"
      class="jdbc.StudentJDBCTemplate">
      <property name="dataSource"  ref="dataSource" />
      <property name="transactionManager"  ref="transactionManager" />    
   </bean>

声明式事务管理

修改StudentJDBCTemplate.create()方法

public void create(String name, Integer age, Integer marks, Integer year){
      try {
         String SQL1 = "insert into Student (name, age) values (?, ?)";
         jdbcTemplateObject.update( SQL1, name, age);
         String SQL2 = "select max(id) from Student";
         int sid = jdbcTemplateObject.queryForInt( SQL2 );
         String SQL3 = "insert into Marks(sid, marks, year) " + 
                       "values (?, ?, ?)";
         jdbcTemplateObject.update( SQL3, sid, marks, year);
         System.out.println("Created Name = " + name + ", Age = " + age);
         throw new RuntimeException("simulate Error condition") ;
      } catch (DataAccessException e) {
         System.out.println("Error in creating record, rolling back");
         throw e;
      }
   }

修改applicationContext.xml文件

利用其AOP特性实现声明式事务管理

   <tx:advice id="txAdvice"  transaction-manager="transactionManager">
      <tx:attributes>
      <tx:method name="create"/>
      </tx:attributes>
   </tx:advice>

   <aop:config>
      <aop:pointcut id="createOperation" 
      expression="execution(* jdbc.StudentJDBCTemplate.create(..))"/>
      <aop:advisor advice-ref="txAdvice" pointcut-ref="createOperation"/>
   </aop:config>

   <bean id="transactionManager"
   class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource"  ref="dataSource" />    
   </bean>

   <bean id="studentJDBCTemplate"  
   class="jdbc.StudentJDBCTemplate">
      <property name="dataSource"  ref="dataSource" />  
   </bean>

猜你喜欢

转载自blog.csdn.net/the_programlife/article/details/80685950
今日推荐