Spring&Mybatis 整合开发基础
首先新建MavenWeb项目,在webapp目录下新建WEB-INF目录,在其中新建web.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>SpringDemo</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
导入相关jar包:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wu.springdemo</groupId>
<artifactId>SpringDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<!-- Mybatis核心包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<!-- Spring核心依赖包 -->
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<!-- Spring核心依赖包 -->
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<!-- Spring核心依赖包 -->
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<!-- 测试包 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
新建pojo,Student.java类:
package com.wu.pojo;
public class Student {
private String name;
private long id;
public Student() {}
public Student(String name,long id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@Override
public String toString() {
return "Student [name=" + name + ", id=" + id + "]";
}
}
Spring对象创建的三种方式:
创建工厂类StudentFactory.java:
package com.wu.pojo;
public class StudentFactory {
public static Student getStudentStatic() {
return new Student();
}
public Student getStudent() {
return new Student();
}
}
在src下创建sprinp的配置文件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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 通过bean无参创建对象 -->
<!-- id表示对象标识 -->
<!-- class为需要创建的类的全路径 -->
<!-- 默认为无参构造方法创建对象 -->
<bean id="student1" class = "com.wu.pojo.Student" />
<!-- 调用相应的有参构造方法创建对象 -->
<bean id = "student2" class = "com.wu.pojo.Student">
<!-- ref表示另一个bean value表示基本数据类型或者String类型 -->
<!-- 由name和id确定参数对应参数列表的有参构造方法 -->
<constructor-arg index = "0" value = "张三"></constructor-arg>
<constructor-arg index = "1" value = "2020" name = "id"></constructor-arg>
</bean>
<!-- 通过实例工厂创建对象 -->
<bean id = "factory" class = "com.wu.pojo.StudentFactory"></bean>
<bean id = "student3" factory-bean="factory" factory-method="getStudent" />
<!-- 通过静态工厂创建对象 -->
<bean id = "student4" class = "com.wu.pojo.StudentFactory" factory-method="getStudentStatic" />
</beans>
创建测试类TestDemo.java:
package com.wu.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.wu.pojo.Student;
public class TestDemo {
@Test
public void test() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student s1 = ac.getBean("student1",Student.class);
System.out.println("无参构造方法创建对象:"+s1);
Student s2 = ac.getBean("student2",Student.class);
System.out.println("有参构造方法创建对象:"+s2);
Student s3 = ac.getBean("student3",Student.class);
System.out.println("实例工厂创建对象:"+s3);
Student s4 = ac.getBean("student4",Student.class);
System.out.println("静态工厂创建对象:"+s4);
// 获取容器中管理的所有对象名
String[] names = ac.getBeanDefinitionNames();
for(String name : names) {
System.out.println(name);
}
}
}
结果:
属性注入:
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- -通过setter赋值 -->
<bean id = "student1" class="com.wu.pojo.Student">
<property name="name" value = "张三"></property>
<!-- 等效于以下语句 -->
<property name="id">
<value>2020</value>
</property>
<!-- 类型为set集合类型 -->
<property name="sets">
<set>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
</set>
</property>
<!-- 当list只要赋值一个时,只需<property name = "lists" value = "值">即可 -->
<property name="lists">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
</list>
</property>
<property name="strs">
<array>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
</array>
</property>
<property name="maps">
<map>
<entry key = "key1" value ="value1"></entry>
<entry key = "key2" value ="value2"></entry>
</map>
</property>
<!-- 属性文件 -->
<!-- <property name="propertys">
<props>
<prop key="key1">value1</prop>
<prop key="key2">value2</prop>
<prop key="key3">value3</prop>
</props>
</property> -->
</bean>
</beans>
Student.java:
package com.wu.pojo;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Student {
private String name;
private long id;
private Set<?> sets;
private List<String> lists;
private String[] strs;
private Map<String,String> maps;
public Map<String, String> getMaps() {
return maps;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
public String[] getStrs() {
return strs;
}
public void setStrs(String[] strs) {
this.strs = strs;
}
public List<String> getLists() {
return lists;
}
public void setLists(List<String> lists) {
this.lists = lists;
}
public Set<?> getSets() {
return sets;
}
public void setSets(Set<?> sets) {
this.sets = sets;
}
public Student() {}
public Student(String name,long id) {
this.name = name;
this.id = id;
}
public Student(long id,String name) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@Override
public String toString() {
return "Student [name=" + name + ", id=" + id + ", sets=" + sets + ", lists=" + lists + ", strs="
+ Arrays.toString(strs) + ", maps=" + maps + "]";
}
}
TestDemo.java:
package com.wu.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.wu.pojo.Student;
public class TestDemo {
@Test
public void test() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student s1 = ac.getBean("student1",Student.class);
System.out.println("通过setter赋值:"+s1);
// 获取容器中管理的所有对象名
String[] names = ac.getBeanDefinitionNames();
for(String name : names) {
System.out.println(name);
}
}
}
结果:
通过setter赋值:Student [name=张三, id=2020, sets=[1, 2, 3, 4], lists=[1, 2, 3, 4], strs=[1, 2, 3, 4], maps={key1=value1, key2=value2}]
student1
DI(依赖注入)
新建Book.java:
package com.wu.pojo;
public class Book {
private String name;
private String author;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public String toString() {
return "Book [name=" + name + ", author=" + author + "]";
}
}
修改Student.java:
package com.wu.pojo;
public class Student {
private String name;
private long id;
private Book book;
@Override
public String toString() {
return "Student [name=" + name + ", id=" + id + ", book=" + book + "]";
}
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
修改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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- -通过setter赋值 -->
<bean id = "student1" class="com.wu.pojo.Student">
<property name="name" value = "张三"></property>
<!-- 等效于以下语句 -->
<property name="id">
<value>2020</value>
</property>
<property name="book" ref = "book"></property>
</bean>
<bean id = "book" class = "com.wu.pojo.Book">
<property name="name">
<value>三体</value>
</property>
<property name="author">
<value>刘慈欣</value>
</property>
</bean>
</beans>
结果:
依赖注入:Student [name=张三, id=2020, book=Book [name=三体, author=刘慈欣]]
student1
book
Mybatis整合
在pom.xml文件中新增包:
<!-- Mybatis-Spring包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<!-- Spring DAO依赖包 -->
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<!-- Spring DAO依赖包 -->
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<!-- Spring Web依赖包 -->
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<!-- Spring 测试包 -->
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<!-- mysql驱动包 -->
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<dependency>
<!-- Servlet包 -->
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
在src文件夹下创建Spring全局配置文件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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 数据源封装类 -->
<bean id = "datasource" class = "org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value = "com.mysql.cj.jdbc.Driver"></property>
<property name="url" value = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC"></property>
<property name="username" value = "root"></property>
<property name="password" value = "root"></property>
</bean>
<!-- 创建SqlSessionFactory对象 -->
<bean id = "factory" class = "org.mybatis.spring.SqlSessionFactoryBean">
<!-- 通过依赖把数据库连接信息注入dataSource属性中 -->
<property name="dataSource" ref = "datasource"></property>
</bean>
<bean id = "mapperconfig" class = "org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 相当于Mybatis全局配置文件中的mapper标签里的属性 -->
<!-- package标签赋值 -->
<property name="basePackage" value = "com.wu.mapper"></property>
<!-- 确定映射关系 -->
<property name="sqlSessionFactory" ref = "factory"></property>
</bean>
<!-- Spring管理业务实现类 -->
<bean id = "studentservice" class = "com.wu.service.StudentServiceImpl">
<property name="studentmapper" ref = "studentMapper"></property>
</bean>
</beans>
创建pojo,Student.java:
package com.wu.pojo;
public class Student {
private String name;
private long id;
private String grade;
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@Override
public String toString() {
return "Student [name=" + name + ", id=" + id + ", grade=" + grade + "]";
}
}
创建映射接口StudentMapper.java:
package com.wu.mapper;
import java.util.List;
import com.wu.pojo.Student;
public interface StudentMapper {
List<Student> findAll();
}
创建配置Mybatis的映射文件StudentMapper.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace = "com.wu.mapper.StudentMapper">
<select id="findAll" resultType = "com.wu.pojo.Student">
select * from student
</select>
</mapper>
创建业务类接口StudentService.java:
package com.wu.service;
import java.util.List;
import com.wu.pojo.Student;
public interface StudentService {
List<Student> show();
}
创建业务接口实现类StudentServiceMapper.java:
package com.wu.service;
import java.util.List;
import com.wu.mapper.StudentMapper;
import com.wu.pojo.Student;
public class StudentServiceImpl implements StudentService{
private StudentMapper studentmapper;
public StudentMapper getStudentmapper() {
return studentmapper;
}
public void setStudentmapper(StudentMapper studentmapper) {
this.studentmapper = studentmapper;
}
@Override
public List<Student> show() {
return studentmapper.findAll();
}
}
创建Servlet:
package com.wu.servlet;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.wu.service.StudentService;
@WebServlet(name = "servlet" , value = {"/findAllStudent"})
public class Myservlet extends HttpServlet{
private static final long serialVersionUID = -6251824731945077927L;
private StudentService studentservice;
@Override
public void init(ServletConfig config) throws ServletException {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
studentservice = ac.getBean("studentservice",StudentService.class);
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
req.setAttribute("studentlist", studentservice.show());
try {
req.getRequestDispatcher("index.jsp").forward(req,res);
}catch(IOException | ServletException e) {
e.printStackTrace();
}
}
}
创建视图层,Index.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Spring&Mybatis</title>
</head>
<body>
<div align = "center">
<h1>学生信息表</h1>
<table border = "1" cellspacing = "0">
<tr>
<th>姓名</th>
<th>学号</th>
<th>班级</th>
</tr>
<c:forEach items = "${requestScope.studentlist}" var = "s">
<tr>
<td>${s.name }</td>
<td>${s.id }</td>
<td>${s.grade }</td>
</tr>
</c:forEach>
</table>
</div>
</body>
</html>
结果:
补充
Spring单例模式和多例模式
设置scope值是singleton时,加载Spring配置文件时候就会创建单实例对象
设置scope值是prototype时,不是在加载Spring配置文件时候创建对象,而是在调用getBean方法时创建多实例对象
<dependencies>
<dependency>
<!-- Spring核心依赖包 -->
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<!-- Spring核心依赖包 -->
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<!-- Spring核心依赖包 -->
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<!-- 测试包 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 默认为单例 -->
<bean id = "student" class = "com.wu.pojo.Student"></bean>
<!-- 多例模式 -->
<bean id = "book" class = "com.wu.pojo.Book" scope = "prototype"></bean>
</beans>
package com.wu.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.wu.pojo.Book;
import com.wu.pojo.Student;
public class TestDemo {
@Test
public void test() {
// 获取spring容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student s1 = ac.getBean("student",Student.class);
Student s2 = ac.getBean("student",Student.class);
System.out.println("学生默认为单例模式");
System.out.println((s1 == s2));
Book b1 = (Book) ac.getBean("book");
Book b2= (Book) ac.getBean("book");
System.out.println("书籍为多例模式");
System.out.println(b1);
System.out.println(b2);
}
}
结果:
学生默认为单例模式
true
书籍为多例模式
com.wu.pojo.Book@f5acb9d
com.wu.pojo.Book@4fb3ee4e
Spring中Bean的生命周期
单例对象
出现:通过读取配置文件后创建容器时对象出现
存活:容器在,对象就一直在
消失:容器销毁,对象消亡
多例对象
出现:使用时创建对象
存活:对象只要是使用过程中就一直存活
消失:对象长时间不使用,并且也没有被引用,由java垃圾回收机制回收
1.通过构造器创建Bean实例(无参构造函数)
2.为Bean的属性设置和对其它Bean引用(调用set方法)
3.把bean实例传递给bean后置处理器的方法
4.调用Bean的初始化的方法
5.把Bean实例传递给Bean后置处理器的方法
6.使用Bean对象
7.容器关闭,Bean销毁
通过注解方式创建bean对象
applicationCotext.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"
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:component-scan base-package="com.wu.pojo"></context:component-scan>
</beans>
Student.java:
package com.wu.pojo;
import org.springframework.stereotype.Component;
@Component(value = "student")
public class Student {
private String name;
private Long id;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
TestDemo.java:
package com.wu.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.wu.pojo.Student;
public class TestDemo {
@Test
public void test() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student s = ac.getBean("student",Student.class);
System.out.println(s);
}
}
结果:
com.wu.pojo.Student@2235eaab
除了Component注解外,也可以使用Controller、Service、Repository三个注解,它们的效果是一样的,但是为了使得三层架构更加清晰,因此,一般将Controller注解用于表现层,Service注解用于业务层,Repository注解用于持久层。
非基本数据类型和基本类型注入注解
@Autowired 根据属性类型进行自动注入
@Qualifier 根据属性名称来进行自动注入(需要配合Autowired注解来使用)
@Resource 根据属性类型或属性名称自动注入
@Value 普通类型属性的注入
pom.xml中添加相关的依赖
<dependency>
<!-- 使用Resource注解需要依赖的jar包,而且JDK版本要为1.6以上 -->
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
IBook.java:
package com.wu.pojo;
public interface IBook {
void lookBook();
}
BookOne.java:
package com.wu.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Repository(value = "book1")
public class BookOne implements IBook{
@Value("书籍一")
private String bookName;
@Value("10001")
private Long bookId;
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public Long getBookId() {
return bookId;
}
public void setBookId(Long bookId) {
this.bookId = bookId;
}
public void lookBook() {
System.out.println("正在看"+bookName);
}
@Override
public String toString() {
return "BookOne [bookName=" + bookName + ", bookId=" + bookId + "]";
}
}
类似的,再建立另外三个pojo类
Student.java:
package com.wu.pojo;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component(value = "student")
public class Student {
@Value("张三")
private String name;
@Value("20210101")
private Long id;
@Value("20")
private Integer age;
@Autowired
private IBook book1 = null;
@Autowired
private IBook book2 = null;
// 这里的Qualifier不能单独使用,其作用为限定对应的bean应该被自动注入
@Autowired
@Qualifier(value = "book3")
private IBook book3 = null;
// 通过独立的Resource注解实现非基本类型的注入
@Resource(name = "book4")
private IBook book4 = null;
@Override
public String toString() {
return "Student [name=" + name + ", id=" + id + ", age=" + age + ", book1=" + book1 + ", book2=" + book2
+ ", book3=" + book3 + ", book4=" + book4 + "]";
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public int getAge() {
return age;
}
}
TestDemo.java:
package com.wu.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.wu.pojo.Student;
public class TestDemo {
@Test
public void test() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student s = ac.getBean("student",Student.class);
System.out.println(s);
}
}
结果:
Student [name=张三, id=20210101, age=20, book1=BookOne [bookName=书籍一, bookId=10001], book2=BookOne [bookName=书籍二, bookId=10002], book3=BookOne [bookName=书籍三, bookId=10003], book4=BookOne [bookName=书籍四, bookId=10004]]
对于Value注解,可以通过spEL表达式完成赋值:
// 通过spEL表达式赋值
@Value("#{book1.getBookId()}")
private Long bookId;
这里需要注意的是:
如果查询结果继承刚好为一个,就将该bean装配给@Autowired指定的属性
如果查询的结果不止一个,那么@Autowired会根据属性名称来查找
如果查询的结果为空,那么会抛出异常。
作用范围注解
和采用xml配置文件方式一样,通过注解的方式默认也为singleton单例模式,如果需要改变为多例,将value的值修改为prototype
package com.wu.pojo;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component(value = "student")
@Scope(value = "prototype") // 多例模式
public class Student {
private String name;
private Long id;
private Integer age;
}
TestDemo.java:
package com.wu.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.wu.pojo.Student;
public class TestDemo {
@Test
public void test() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student s1 = ac.getBean("student",Student.class);
Student s2 = ac.getBean("student",Student.class);
System.out.println(s1);
System.out.println(s2);
}
}
结果:
com.wu.pojo.Student@1bd39d3c
com.wu.pojo.Student@6f19ac19
AOP基础
相关依赖包建立:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wu.springdemo</groupId>
<artifactId>SpringDemo3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
定义代理接口IProxy.java:
package com.wu.proxy;
public interface IProxy {
/**
* 代理对象执行方法
*/
void proxyAction();
}
定义代理接口实现类ProxyImpl.java:
package com.wu.proxy;
public class ProxyImpl implements IProxy{
@Override
public void proxyAction() {
System.out.println("代理业务执行…");
}
}
定义业务增强类Service.java:
package com.wu.service;
class Service {
/**
* 前置通知
*/
public void before() {
System.out.println("前置通知…");
}
/**
* 最终通知
*/
public void after() {
System.out.println("最终通知…");
}
/**
* 异常通知
*/
public void afterThrowing() {
System.out.println("异常通知…");
}
/**
* 后置通知
*/
public void afterReturning() {
System.out.println("后置通知…");
}
}
spring配置文件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: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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置spring的IOC,将真实代理类实例化 -->
<bean id = "proxy" class = "com.wu.proxy.ProxyImpl"></bean>
<!-- 配置spring的IOC,将扩展业务类实例化 -->
<bean id = "service" class = "com.wu.service.Service"></bean>
<aop:config>
<!-- 配置切面 -->
<aop:aspect id = "serviceAdvice" ref = "service">
<!-- 配置通知的类型,并且建立通知方法和切入点方法的关联 -->
<!-- pointcut属性使用切入点表达式匹配 -->
<aop:before method = "before" pointcut = "execution(* com.wu.proxy.*.*(..))"/>
<aop:after-returning method = "afterReturning" pointcut = "execution(* com.wu.proxy.*.*(..))"/>
<aop:after-throwing method = "afterThrowing" pointcut = "execution(* com.wu.proxy.*.*(..))"/>
<aop:after method="after" pointcut = "execution(* com.wu.proxy.*.*(..))"/>
</aop:aspect>
</aop:config>
</beans>
测试类:
package com.wu.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.wu.proxy.IProxy;
public class TestDemo {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
IProxy proxy = context.getBean("proxy",IProxy.class);
proxy.proxyAction();
}
}
结果:
如果在代理类中添加异常语句:
System.out.println(1/0);
其结果为:
环绕通知:
环绕通知是Spring AOP中最强大的通知,它可以同时实现前置通知和后置通知。
<aop:config>
<!-- 对当前config标签内所有切面共享 -->
<!-- 如果pointcut标签放置入aspect标签内,则只能在aspect的标签内使用 -->
<aop:pointcut id = "proxyPointcut" expression="execution(* com.wu.proxy.*.*(..))"></aop:pointcut>
<!-- 配置切面 -->
<aop:aspect id = "serviceAdvice" ref = "service">
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref = "proxyPointcut"/>
</aop:aspect>
</aop:config>
/**
* 环绕通知
*/
public void around(ProceedingJoinPoint proc) {
System.out.println("环绕之前通知…");
try {
proc.proceed();
System.out.println("环绕之后通知…");
}catch(Throwable e) {
System.out.println("环绕异常通知…");
}finally{
System.out.println("环绕最终通知…");
}
}
结果: