Spring5框架学习
Spring框架
Spring是轻量级的开源的JavaEE框架
可以解决企业应用开发的复杂性
两个核心部分:IOC和Aop
- IOC:控制反转,把创建对象过程交给Spring进行管理
- Aop:面向切面,不修改源代码进行功能增强
下载
在idea中创建一个maven项目,去 https://mvnrepository.com/ 搜索Spring core的依赖并复制到pom.xml中可自动下载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.xlh</groupId>
<artifactId>springdemo01</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
第一个例子
通过上述方式可创建一个项目,并使用spring方法创建类
创建一个
src/main/java/cn/xlh/add.java
1
2
3
4
5
6
7package cn.xlh;
public class add {
public void add_test(){
System.out.println("测试中:add_test()");
}
}在
src/main/resources
下创建一个bean1.xml文件,写入配置信息1
2
3
4
5
6
7
<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">
<!--配置add对象创建-->
<bean id="add" class="cn.xlh.add"></bean>
</beans>创建一个
src/test/java/cn/xlh/testadd.java
用于测试1
2
3
4
5
6
7
8
9
10
11
12
13
14
15package cn.xlh;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class testadd {
public void testAdd(){
// 加载配置文件
ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml");
add add01 = context.getBean("add", add.class);
add01.add_test();
}
}运行即可
整体结构
IOC容器
什么是IOC
- 控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理
- 使用IOC目的:为了耦合度降低
- 第一个例子就是IOC案例
IOC底层原理
- xml解析、工厂模式、反射

接口
- IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
- Spring提供IOC容器实现两种方式:(两个接口)
- BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用
- 加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
- ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用
- 加载配置文件时候就会把在配置文件对象进行创建
- ApplicationContext接口有实现类
- BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用
Bean管理
- 基于xml方式创建对象
(1)在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
(2)在bean标签有很多属性,介绍常用的属性
1 | id属性:唯一标识 |
(3)创建对象时候,默认也是执行无参数构造方法完成对象创建
1 | <!--配置add对象创建--> |
注入属性
第一种注入方式:使用set方法进行注入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// java源文件
package cn.xlh;
public class book {
private String book_name;
private String book_author;
public void setBook_name(String book_name) {
this.book_name = book_name;
}
public void setBook_author(String book_author) {
this.book_author = book_author;
}
public String testDemo(){
return this.book_author+" "+this.book_name;
}
}1
2
3
4
5
6<!-- xml文件 -->
<bean id="book" class="cn.xlh.book">
<!--属性注入,name为属性名,value为属性值-->
<property name="book_author" value="肖林航"></property>
<property name="book_name" value="java"></property>
</bean>第二种方式:使用有参构造函数注入
1
2
3
4
5
6
7
8
9
10
11
12
13
14package cn.xlh;
public class book {
private String book_name;
private String book_author;
public book(String book_name, String book_author) {
this.book_name = book_name;
this.book_author = book_author;
}
public String testDemo() {
return this.book_author + " " + this.book_name;
}
}1
2
3
4
5<bean id="book" class="cn.xlh.book">
<!--构造函数参数-->
<constructor-arg name="book_name" value="java"></constructor-arg>
<constructor-arg name="book_author" value="肖林航"></constructor-arg>
</bean>
xml注入其他类型
null
1
2
3<property name="book_name">
<null></null>
</property>包含特殊符号
1
2
3
4<!--属性值包含特殊符号 1 把<>进行转义 < > 2 把带特殊符号内容写到CDATA -->
<property name="address">
<value><![CDATA[<<南京>>]]></value>
</property>注入属性-外部bean
- 创建两个类 service类和dao类
- 在service调用dao里面的方法
- 在spring配置文件中进行配置
1
2
3
4
5package dao;
public interface User {
public void update();
}1
2
3
4
5
6
7package dao;
public class UserImpl implements User {
public void update() {
System.out.println("dao update....");
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package service;
import dao.User;
public class Userservice {
private User user;
public void setUser(User user) {
this.user = user;
}
public void load() {
System.out.println("service loading.....");
// 调用dao方法
user.update();
// 传统方法
// User dao=new UserImpl();
// dao.update();
}
}1
2
3
4
5
6
7
8<bean id="Userservice" class="service.Userservice">
<!--注入userdao对象
name:属性名称
ref:创建userdao对象的标签id
-->
<property name="user" ref="dao"></property>
</bean>
<bean id="dao" class="dao.UserImpl"></bean>注入属性-内部bean
- 在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28//部门类
public class Dept {
private String dname;
public void setDname(String dname) {
this.dname = dname;
}
}
//员工类
public class Emp {
private String ename;
private String gender;
// 员工属于某一个部门,使用对象形式表示
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setGender(String gender) {
this.gender = gender;
}
}- 在spring配置文件中进行配置
1
2
3
4
5
6
7
8
9
10<!--内部bean-->
<bean id="emp" class="com.atguigu.spring5.bean.Emp"> <!--设置两个普通属性-->
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property> <!--设置对象类型属性-->
<property name="dept">
<bean id="dept" class="com.atguigu.spring5.bean.Dept">
<property name="dname" value="安保部"></property>
</bean>
</property>
</bean>注入属性-级联赋值
1
2
3
4
5
6
7
8
9
10<!-- 第一种级联赋值-->
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
<!--设置两个普通属性-->
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property> <!--级联赋值-->
<property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="com.atguigu.spring5.bean.Dept">
<property name="dname" value="财务部"></property>
</bean>注入集合类型属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48package students;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Student {
//数组
private String[] arrays;
//List
private List<String> list;
//map
private Map<String, String> map;
//set
private Set<String> set;
public String[] getArrays() {
return arrays;
}
public List<String> getList() {
return list;
}
public Map<String, String> getMap() {
return map;
}
public Set<String> getSet() {
return set;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setArrays(String[] arrays) {
this.arrays = arrays;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30<bean id="stu" class="students.Student">
<!--注入数组类型-->
<property name="arrays">
<array>
<value>java</value>
<value>php</value>
</array>
</property>
<!--注入List类型-->
<property name="list">
<list>
<value>JAVA</value>
<value>PHP</value>
</list>
</property>
<!--注入Map类型-->
<property name="map">
<map>
<entry key="java" value="JAVA"></entry>
<entry key="php" value="PHP"></entry>
</map>
</property>
<!--注入Set类型-->
<property name="set">
<set>
<value>HTML</value>
<value>CSS</value>
</set>
</property>
</bean>注入集合类型属性(集合存储对象)
1
2
3
4
5
6
7
8
9
10
11
12
13
14<!--创建多个course对象-->
<bean id="course1" class="com.atguigu.spring5.collectiontype.Course">
<property name="cname" value="Spring5框架"></property>
</bean>
<bean id="course2" class="com.atguigu.spring5.collectiontype.Course">
<property name="cname" value="MyBatis框架"></property>
</bean>
<!--注入list集合类型,值是对象-->
<property name="courseList">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>把集合注入部分提取出来
1
2
3
4<!--在spring配置文件中引入名称空间 util -->
<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:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">1
2
3
4
5
6
7
8
9
10
11<!-- 使用util标签完成list集合注入提取 -->
<!--1 提取list集合类型属性注入-->
<util:list id="bookList">
<value>易筋经</value>
<value>九阴真经</value>
<value>九阳神功</value>
</util:list>
<!--2 提取list集合类型属性注入使用-->
<bean id="book" class="com.atguigu.spring5.collectiontype.Book">
<property name="list" ref="bookList"></property>
</bean>
IOC操作 Bean 管理
FactoryBean
Spring有两种类型bean,一种普通bean,另外一种工厂bean(FactoryBean)
普通bean:在配置文件中定义bean类型就是返回类型
工厂bean:在配置文件定义bean类型可以和返回类型不一样
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// 创建类,让这个类作为工厂bean,实现接口 FactoryBean
// 实现接口里面的方法,在实现的方法中定义返回的bean类型
package factory;
import cn.xlh.book;
import org.springframework.beans.factory.FactoryBean;
public class facbean implements FactoryBean<book> {
//定义返回bean的类型
public book getObject() throws Exception {
String s1 = "111", s2 = "222";
book book = new book(s1, s2);
return book;
}
public Class<?> getObjectType() {
return null;
}
public boolean isSingleton() {
return false;
}
}1
<bean id="fac" class="factory.facbean"></bean>
bean 作用域
在Spring里面,设置创建bean实例是单实例还是多实例
在Spring里面,默认情况下,bean是单实例对象
1
2
3book book01 = context.getBean("book", book.class);
book book02 = context.getBean("book", book.class);
// 默认两次产生的是同一个bean标签的scope属性可以设置单实例或多实例,
singleton
为单实例(默认),prototype
为多实例1
2
3
4
5<bean id="book" class="cn.xlh.book" scope="prototype">
<!--属性注入,name为属性名,value为属性值-->
<property name="book_author" value="肖林航"></property>
<property name="book_name" value="java"></property>
</bean>区别
- singleton单实例,prototype多实例
- 设置scope值是singleton时候,加载spring配置文件时候就会创建单实例对象
- 设置scope值是prototype时候,不是在加载spring配置文件时候创建 对象,在调用getBean方法时候创建多实例对象
bean 生命周期
- 从对象创建到对象销毁的过程
- 生命周期
- 通过构造器创建bean实例(无参数构造)
- 为bean的属性设置值和对其他bean引用(调用set方法)
- 调用bean的初始化的方法(需要进行配置初始化的方法)
- bean可以使用了(对象获取到了)
- 当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁的方法)
- bean的后置处理器,bean生命周期有七步
- 通过构造器创建bean实例(无参数构造)
- 为bean的属性设置值和对其他bean引用(调用set方法)
- 把bean实例传递bean后置处理器的方法postProcessBeforeInitialization
- 调用bean的初始化的方法(需要进行配置初始化的方法)
- 把bean实例传递bean后置处理器的方法 postProcessAfterInitialization
- bean可以使用了(对象获取到了)
- 当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁的方法)
xml 自动装配
根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入
根据属性名称自动注入
1
2
3
4<!--实现自动装配 bean标签属性autowire,配置自动装配 autowire属性常用两个值: byName根据属性名称注入 ,注入值bean的id值和类属性名称一样 byType根据属性类型注入 -->
<bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byName">
</bean>
<bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean>根据属性类型自动注入
1
2
3<!--实现自动装配 bean标签属性autowire,配置自动装配 autowire属性常用两个值: byName根据属性名称注入 ,注入值bean的id值和类属性名称一样 byType根据属性类型注入 -->
<bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byType">
</bean> <bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean>
外部属性文件
* 创建外部属性文件,properties格式文件,写数据库信息
* 把外部properties属性文件引入到spring配置文件中引入context名称空间
* 在spring配置文件使用标签引入外部属性文件
基于注解管理(重要)
什么是注解
(1)注解是代码特殊标记,格式:@注解名称(属性名称=属性值, 属性名称=属性值..)
(2)使用注解,注解作用在类上面,方法上面,属性上面
(3)使用注解目的:简化xml配置
Spring针对Bean管理中创建对象提供注解
(1)@Component
(2)@Service
(3)@Controller
(4)@Repository
上面四个注解功能是一样的,都可以用来创建bean实例
基于注解方式实现对象创建
引入spring-aop依赖
bean1.xml中开启组件扫描
1
<context:component-scan base-package="cn.xlh"></context:component-scan>
创建类,在类上面添加创建对象注解
1
2
3
4
5
6
7
8
9
10package cn.xlh;
import org.springframework.stereotype.Component;
// 相当于<bean id="book1" class="..."><bean>
//value可省略,默认为类名(首字母小写)
public class book {
private String book_name;
private String book_author;
}测试
1
2
3
4
5
6
7
public void test05() {
// 加载配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
book book1 = context.getBean("book1", book.class);
System.out.println(book1);
}
细节管理
1 | <!--示例1 use-default-filters="false" 表示现在不使用默认filter,自己配置filter context:include-filter ,设置扫描哪些内容 --> |
属性注入
@Autowired:根据属性类型进行自动装配
- 把service和dao对象创建,在service和dao类添加创建对象注解
- 在service注入dao对象,在service类添加dao类型属性,在属性上面使用注解
1
2
3
4
5
6
7
8package dao;
import org.springframework.stereotype.Repository;
public interface UserDao {
public void add();
}1
2
3
4
5
6
7
8
9
10package dao;
import org.springframework.stereotype.Repository;
public class UserDaoImpl implements UserDao{
public void add() {
System.out.println("UserDaoImpl add....!");
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18javapackage service;
import dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
public class Service2 {
//不需要set方法,添加注解实现
private UserDao userDao;
public void addTest() {
System.out.println("service loading.....");
// 调用dao方法
userDao.add();
}
}- 测试即可
@Qualifier:根据名称进行注入。@Qualifier注解的使用,和上面@Autowired一起使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package service;
import dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
public class Service2 {
//不需要set方法,添加注解实现
//给实现类注解加名字后,按照名字创建该类
private UserDao userDao;
public void addTest() {
System.out.println("service loading.....");
// 调用dao方法
userDao.add();
}
}@Resource:可以根据类型注入,可以根据名称注入
1
2
3//@Resource // 按照属性类型
// 按照属性名
private UserDao userDao;@Value:注入普通类型属性
1
2// 将xlh注入name中
private String name;
完全注解开发
创建配置类,替代xml配置文件
1
2
3
4
5
6
7
8
9
10package config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
// 作为配置类,代替xml
public class SpringConfig {
}编写测试类
1
2
3
4
5
6
7
public void test06() {
// 加载配置文件
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
Service2 service2 = context.getBean("service2", Service2.class);
service2.addTest();
}
AOP
- 面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
- 通俗描述:不通过修改源代码方式,在主干功能里面添加新功能。
动态代理
有接口情况,使用JDK动态代理
- 创建接口实现类代理对象,增强类的方法
没有接口情况,使用CGLIB动态代理
- 创建子类的代理对象,增强类的方法
JDK动态代理
使用JDK动态代理,使用Proxy类里面的方法创建代理对象
调用newProxyInstance方法
1
2static Object newProxyInstance(ClassLoader loader, 类<?>[] interfaces, InvocationHandler h)
返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序。- 方法有三个参数:
- 第一参数,类加载器
- 第二参数,增强方法所在的类,这个类实现的接口,支持多个接口
- 第三参数,实现这个接口InvocationHandler,创建代理对象,写增强的部分
- 方法有三个参数:
编写JDK动态代理代码
- 创建接口,定义方法
1
2
3
4
5
6
7
8
9
10
11
12
13package dao;
public class CarDaoImpl implements CarDao {
public int add(int a, int b) {
return 0;
}
public String update(String id) {
return null;
}
}- 创建接口实现类,实现方法
1
2
3
4
5
6
7
8
9
10
11
12
13package dao;
public class CarDaoImpl implements CarDao {
public int add(int a, int b) {
return 0;
}
public String update(String id) {
return null;
}
}- 使用Proxy类创建接口代理对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45package dao;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class JDKProxy {
public static void main(String[] args) {
//创建接口实现类代理对象
Class[] interfaces={CarDao.class};
//Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
// //匿名方式
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// return null;
// }
//});
CarDaoImpl carDao=new CarDaoImpl();
CarDao carDao1= (CarDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(),interfaces,new CarDaoProxy(carDao));
int res=carDao1.add(10,20);
System.out.println(res);
}
}
//创建代理对象
class CarDaoProxy implements InvocationHandler{
//创建的是谁的对象就把谁传过来
private Object obj;
public CarDaoProxy(Object obj){
this.obj=obj;
}
//增强的逻辑
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法之前
System.out.println("方法之前执行....."+method.getName()+"传递参数:"+ Arrays.toString(args));
//被增强的方法执行
Object res=method.invoke(obj,args);
//方法之后
System.out.println("方法之后执行..."+obj);
return res;
}
}
AOP操作术语
- 连接点
- 类里哪些方法可以被增强,这些方法就被认为是连接点
- 切入点
- 实际被增强的方法,称为切入点
- 通知(增强)
- 实际增强的逻辑部分称为通知
- 类型
- 前置通知‘
- 后置通知
- 环绕通知
- 异常通知
- 最终通知
- 切面
- 把通知应用到切入点
AOP准备
Spring框架一般都是基于AspectJ实现AOP操作
- AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spirng框架一起使用,进行AOP操作
基于AspectJ实现AOP操作
- 基于xml配置文件实现
- 基于注解方式实现(使用)
在项目工程里面引入AOP相关依赖
切入点表达式
- 切入点表达式作用:知道对哪个类里面的哪个方法进行增强
- 语法结构:
execution([权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]) )
举例
1
2
3
4
5
6举例1:对com.atguigu.dao.BookDao类里面的add进行增强
execution(* com.atguigu.dao.BookDao.add(..))
举例2:对com.atguigu.dao.BookDao类里面的所有的方法进行增强
execution(* com.atguigu.dao.BookDao.* (..))
举例3:对com.atguigu.dao包里面所有类,类里面所有方法进行增强
execution(* com.atguigu.dao.*.* (..))
AOP操作(基于AspectJ注解)
创建类,在类里面定义方法
1
2
3
4
5
6
7
8package aop;
public class User {
public void add(){
System.out.println("aop.User add.....");
}
}创建增强类(编写增强逻辑)
- 在增强类里面,创建方法,让不同方法代表不同通知类型
1
2
3
4
5
6
7
8
9package aop;
//增强类
public class UserProxy {
//前置通知
public void before(){
System.out.println("before.....");
}
}进行通知的配置
在spring配置文件中,开启注解扫描
1
<context:component-scan base-package="aop"></context:component-scan>
使用注解创建User和UserProxy对象
1
2
3
4
5
6
public class User {
//增强类
public class UserProxy {在增强类上面添加注解 @Aspect
1
2
3
4//增强类
//生成代理对象
public class UserProxy {在spring配置文件中开启生成代理对象
1
2<!--开启Aspect生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>配置不同类型的通知
- 在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44package aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
//增强类
//生成代理对象
public class UserProxy {
//前置通知
//Before 注解表示前置通知
public void before() {
System.out.println("before.....");
}
//后置通知(返回通知)
public void afterReturning() {
System.out.println("afterReturning.....");
}
//最终通知
public void after() {
System.out.println("after.....");
}
//异常通知
public void afterThrowing() {
System.out.println("afterThrowing.....");
}
//环绕通知
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕前...");
// 被增强的方法执行
proceedingJoinPoint.proceed();
System.out.println("环绕后...");
}
}
测试及结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void test07() {
// 加载配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
User user = context.getBean("user", User.class);
user.add();
}
// 输出结果
环绕前...
before.....
aop.User add.....
afterReturning.....
after.....
环绕后...
Process finished with exit code 0相同切入点抽取
1
2
3
4
5
6
7
8
9
10
11
12//相同切入点抽取
public void pointcut() {
}
//前置通知
//Before 注解表示前置通知
public void before() {
System.out.println("before.....");
}有多个增强类多同一个方法进行增强,设置增强类优先级
1
2
3
4
5//增强类
//生成代理对象
public class UserProxy {完全使用注解开发
创建配置类,不需要创建xml配置文件
1
2
3
4
5
6
public class ConfigAop {
}
AOP操作(AspectJ配置文件)
创建两个类,增强类和被增强类,创建方法
在spring配置文件中创建两个类对象
1
2
3<!--创建对象-->
<bean id="book" class="aop.Book"></bean>
<bean id="bookProxy" class="aop.BookProxy"></bean>在spring配置文件中配置切入点
1
2
3
4
5
6
7
8
9
10<!--配置aop增强-->
<aop:config>
<!--切入点-->
<aop:pointcut id="p" expression="execution(* aop.Book.buy())"></aop:pointcut>
<!--配置切面-->
<aop:aspect ref="bookProxy">
<!--增强作用在具体的方法上-->
<aop:before method="before" pointcut-ref="p"></aop:before>
</aop:aspect>
</aop:config>
JdbcTemplate
什么是JdbcTemplate
Spring框架对JDBC进行封装,使用JdbcTemplate方便实现对数据库操作。
准备工作
引入相关jar包
在spring配置文件配置数据库连接池
1
2
3
4
5
6<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="jdbc:mysql://localhost:3306/test"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
</bean>配置JdbcTemplate对象,注入DataSource
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<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 https://www.springframework.org/schema/context/spring-context.xsd">
<!--开启组件扫描-->
<context:component-scan base-package="JdbcTemplate"></context:component-scan>
<!--数据库连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="jdbc:mysql://localhost:3306/test"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
</bean>
<!--jdbcTemplate对象-->
<bean id="dbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>创建service类,创建dao类,在dao注入jdbcTemplate对象
1
2
3
4package JdbcTemplate.dao;
public interface BookDao {
}1
2
3
4
5
6
7
8
9
10
11
12package JdbcTemplate.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
public class BookDaoImpl implements BookDao{
//注入jdbctemplate
private JdbcTemplate jdbcTemplate;
}1
2
3
4
5
6
7
8
9
10
11
12
13package JdbcTemplate.service;
import JdbcTemplate.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
public class BookService {
//注入BookDao
private BookDao bookDao;
}
JdbcTemplate操作数据库(添加)
- 在dao进行数据库添加操作
- 调用JdbcTemplate对象里面update方法实现添加操作
- 有两个参数
- 第一个参数:sql语句
- 第二个参数:可变参数,设置sql语句值
1 | package JdbcTemplate.entity; |
1 | package JdbcTemplate.dao; |
1 | package JdbcTemplate.dao; |
1 | package JdbcTemplate.dao; |
1 |
|
JdbcTemplate操作数据库(修改和删除)
1 |
|
JdbcTemplate操作数据库(查询)
查询返回某个值
- 查询表里面有多少条记录,返回是某个值
1 | //查询记录数 |
查询返回对象
- 场景:查询图书详情
- 有三个参数
- 第一个参数:sql语句
- 第二个参数:RowMapper是接口,针对返回不同类型数据,使用这个接口里面实现类完成数据封装
- 第三个参数:sql语句值
1 |
|
查询返回集合
- 场景:查询图书列表分页…
- 有三个参数
- 第一个参数:sql语句
- 第二个参数:RowMapper是接口,针对返回不同类型数据,使用这个接口里面实现类完成数据封装
- 第三个参数:sql语句值
1 |
|
JdbcTemplate操作数据库(批量操作)
- JdbcTemplate实现批量添加操作
- 有两个参数
- 第一个参数:sql语句
- 第二个参数:List集合,添加多条记录数据
1 | //批量添加 |