1.介绍
官网:https://spring.io/
Spring 让每个人都可以更快、更轻松、更安全地编写 Java。Spring 对速度、简单性和生产力的关注使其成为世界上最受欢迎的Java 框架。
我们使用了 Spring 框架附带的许多工具,并获得了许多开箱即用的解决方案所带来的好处,并且不必担心编写大量额外的代码——这确实为我们节省了一些时间和能量。
2.特征
- 核心技术:依赖注入、事件、资源、i18n、验证、数据绑定、类型转换、SpEL、AOP。
- 测试:模拟对象、TestContext 框架、Spring MVC 测试、
WebTestClient
.
- 数据访问:事务、DAO 支持、JDBC、ORM、编组 XML。
- Spring MVC和 Spring WebFlux Web 框架。
- 集成:远程处理、JMS、JCA、JMX、电子邮件、任务、调度、缓存。
- 语言:Kotlin、Groovy、动态语言。
3.核心技术
IOC:控制反转,将对象的创建权交给了Spring去管理
DI:依赖注入,把数据给创建好的对象中的属性进行赋值
AOP:面向切面编程,底层是代理模式
4.Bean的创建
org.springframework.beans
和org.springframework.context
包是 Spring Framework 的 IoC 容器的基础。该 BeanFactory
接口提供了一种高级配置机制,能够管理任何类型的对象。 ApplicationContext
是 BeanFactory
的子接口。它补充说:
- 更容易与 Spring 的 AOP 功能集成
- 消息资源处理(用于国际化)
- 活动发布
- 应用层特定上下文,例如
WebApplicationContext
用于 Web 应用程序的上下文。
org.springframework.context.ApplicationContext
接口代表 Spring IoC 容器,负责实例化、配置和组装 bean。
4.1无参构造创建
导入依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.20</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> </dependencies>
|
创建User实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.coutrue.pojo;
public class User {
private Integer id; private String name; private String password;
public User() { System.out.println("无参构造"); } }
|
编写applicationContext.xml配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?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 https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.coutrue.pojo.User"> </bean>
</beans>
|
编写测试类
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
| package com.couture.test;
import com.couture.pojo.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
@Test public void testUser() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User)applicationContext.getBean("user");
System.out.println(user);
} }
|
4.2工厂创建
创建工厂类
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 48
| package com.couture.factory;
import com.couture.pojo.User;
public class UserFactory {
public User getUser() {
try { return (User)Class.forName("com.qf.pojo.User").newInstance(); } catch (Exception e) { e.printStackTrace(); }
throw new RuntimeException("创建User对象异常"); }
public static User getUserStatic() {
try { return (User)Class.forName("com.qf.pojo.User").newInstance(); } catch (Exception e) { e.printStackTrace(); }
throw new RuntimeException("创建User对象异常"); } }
|
配置applicationContext.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?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 https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.coutrue.factory.UserFactory" factory-method="getUserStatic"></bean>
</beans>
|
4.3简单工厂模式
Car
1 2 3 4 5 6 7 8 9 10 11 12
| package com.couture.factorymode.simplefactory;
public interface Car {
public void run(); }
|
1 2 3 4 5 6 7 8 9 10 11
| package com.couture.factorymode.simplefactory;
public class BaoSJ implements Car { @Override public void run() { System.out.println("保时捷在飞驰..."); } }
|
1 2 3 4 5 6 7 8 9 10 11
| package com.couture.factorymode.simplefactory;
public class FaLL implements Car { @Override public void run() { System.out.println("法拉利在飞驰..."); } }
|
java
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
| package com.couture.factorymode.simplefactory;
public class CarFactory {
public static BaoSJ creatBaoSJ() { try { return (BaoSJ)Class.forName("com.coutrue.factorymode.simplefactory.BaoSJ").newInstance(); } catch (Exception e) { e.printStackTrace(); } return null; }
public static FaLL creatFaLL() { try { return (FaLL)Class.forName("com.coutrue.factorymode.simplefactory.FaLL").newInstance(); } catch (Exception e) { e.printStackTrace(); } return null; } }
|
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.couture.factorymode.simplefactory;
public class Test { public static void main(String[] args) {
BaoSJ baoSJ = CarFactory.creatBaoSJ(); baoSJ.run();
FaLL faLL = CarFactory.creatFaLL(); faLL.run();
} }
|
4.4抽象工厂模式
Car
1 2 3 4 5 6 7 8 9 10 11 12
| package com.couture.factorymode.abstractfactory;
public interface Car {
public void run(); }
|
1 2 3 4 5 6 7 8 9 10 11
| package com.couture.factorymode.abstractfactory;
public class BaoSJ implements Car { @Override public void run() { System.out.println("保时捷在飞驰..."); } }
|
1 2 3 4 5 6 7 8 9 10 11
| package com.couture.factorymode.abstractfactory;
public class FaLL implements Car { @Override public void run() { System.out.println("法拉利在飞驰..."); } }
|
CarFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.couture.factorymode.abstractfactory;
public interface CarFactory {
public Car createCar();
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.couture.factorymode.abstractfactory;
public class BaoSJFactory implements CarFactory{
@Override public Car createCar() { try { return (BaoSJ)Class.forName("com.qf.factorymode.abstractfactory.BaoSJ").newInstance(); } catch (Exception e) { e.printStackTrace(); } return null; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.couture.factorymode.abstractfactory;
public class FaLLFactory implements CarFactory{ @Override public Car createCar() { try { return (FaLL)Class.forName("com.qf.factorymode.abstractfactory.FaLL").newInstance(); } catch (Exception e) { e.printStackTrace(); } return null; } }
|
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.couture.factorymode.abstractfactory;
public class Test { public static void main(String[] args) {
BaoSJFactory baoSJFactory = new BaoSJFactory(); Car baoSJ = baoSJFactory.createCar(); baoSJ.run();
FaLLFactory faLLFactory = new FaLLFactory(); Car faLL = faLLFactory.createCar(); faLL.run();
} }
|
5.Bean的作用范围
5.1scope属性
bean标签的scope属性:指定当前bean的作用范围
取值:
singleton:单例( 默认值 )
prototype:多例
request:作用于Web应用的请求范围
session:作用于Web应用的会话范围
global-session:作用于集群环境Web应用的会话范围(全局会话)
1 2 3 4 5 6 7
|
<bean id = "user" class = "com.couture.pojo.User" scope="prototype"> </bean>
|
5.2单例模式-懒汉式
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
| package com.couture.singletonmode;
public class SingletonLazy {
private SingletonLazy() {}
private static SingletonLazy singletonLazy = null;
public static synchronized SingletonLazy getSingletonLazy() { if(null == singletonLazy) { singletonLazy = new SingletonLazy(); }
return singletonLazy; }
}
|
5.3单例模式-饿汉式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.couture.singletonmode;
public class SingletonHungry {
private SingletonHungry() {}
private static SingletonHungry singletonHungry = new SingletonHungry();
public static SingletonHungry getSingletonHungry() { return singletonHungry; } }
|
5.4单例模式-双重校验锁
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
| package com.couture.singletonmode;
public class SingletonLock {
private SingletonLock() {}
private static SingletonLock singletonLock = null;
public static SingletonLock getSingletonLock() { if(null == singletonLock){ synchronized (SingletonLock.class) { if(null == singletonLock){ singletonLock = new SingletonLock(); } } } return singletonLock; } }
|
6.Bean生命周期
1 2 3 4 5 6 7 8 9 10
|
<bean id = "user" class = "com.couture.pojo.User" scope="singleton" init-method="initUser" destroy-method="destroyUser"> </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
| package com.couture.pojo;
public class User {
private Integer id; private String name; private String password;
public User() { System.out.println("无参构造"); }
public void initUser() { System.out.println("User 初始化方法"); }
public void destroyUser() { System.out.println("User 销毁方法"); }
}
|
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
@Test public void testLife() { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) applicationContext.getBean("user");
System.out.println(user);
applicationContext.close(); }
|
7.依赖注入
DI:Dependency Injection:给创建对象中的属性赋值
IOC作用:降低程序间耦合(依赖关系)
依赖关系维护:以后都交给Spring进行管理
可注入类型:
基本数据类型以及包装类
String类
类类型( 其他Bean类型 )
复杂类型:集合,数组…
7.1set方法注入
applicationContext.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
| <?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 https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="firstCar" class="com.couture.pojo.Car"> <property name="cid" value="20001"></property> <property name="cname" value="保时捷"></property> </bean>
<bean id = "user" class = "com.coutrue.pojo.User">
<property name="id" value="1001"></property> <property name="name" value="张三"></property> <property name="password" value="123"></property> <property name="car" ref="firstCar"></property> </bean>
</beans>
|
实体类
1 2 3 4 5 6 7 8 9 10 11
| package com.couture.pojo;
import lombok.Data;
@Data public class Car {
private Integer cid; private String cname;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.couture.pojo;
import lombok.Data;
@Data public class User {
private Integer id; private String name; private String password;
private Car car; }
|
测试
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
| package com.couture.test;
import com.qf.pojo.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
@Test public void testUser(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User user =(User)applicationContext.getBean("user");
System.out.println(user); } }
|
7.2复杂类型注入
1.注入数组对应的标签:array
2.注入LIst以及Set集合的标签:list,set
3.注入Map以及Propertis的标签:map,properties
创建实体类CollectionVo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package com.couture.vo;
import lombok.Data;
import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set;
@Data public class CollectionVo {
private Integer [] arr; private List list; private Set set; private Map map; private Properties properties;
}
|
在applicationContext.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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| <bean id="collectionVo" class="com.coutrue.vo.CollectionVo"> <property name="arr"> <array> <value>123</value> <value>456</value> <value>789</value> </array> </property>
<property name="list"> <list> <value>jack</value> <value>jack</value> <value>rose</value> <ref bean="user"></ref> </list> </property>
<property name="set"> <set> <value>张三</value> <value>张三</value> <value>李四</value> <ref bean="user"></ref> </set> </property>
<property name="map"> <map> <entry key="1001" value="张三"></entry> <entry key-ref="user" value-ref="firstCar"></entry> </map> </property>
<property name="properties"> <props> <prop key="username">root</prop> <prop key="password">root</prop> <prop key="url">jdbc:mysql:///db_name?serverTimezone=Asia/Shanghai</prop> <prop key="driverClassName">com.mysql.cj.jdbc.Driver</prop> </props> </property>
</bean>
|
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
@Test public void testCollectionVo() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
CollectionVo collectionVo = (CollectionVo) applicationContext.getBean("collectionVo");
System.out.println(collectionVo); }
|
7.3构造器注入( 不常用 )
创建Car
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.couture.pojo;
import lombok.Data;
@Data public class Car {
private Integer cid; private String cname;
public Car(Integer cid, String cname) { this.cid = cid; this.cname = cname; } }
|
创建User
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
| package com.couture.pojo;
import lombok.Data;
@Data public class User {
private Integer id; private String name; private String password;
private Car car;
public User(Integer id, String name, String password, Car car) { this.id = id; this.name = name; this.password = password; this.car = car;
System.out.println("第一个构造器"); }
public User(String name, Integer id,String password, Car car) { this.id = id; this.name = name; this.password = password; this.car = car;
System.out.println("第二个构造器"); } }
|
配置applicationContext.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 34 35 36 37 38 39
| <?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 https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="firstCar" class="com.couture.pojo.Car">
<constructor-arg name="cid" value="20001" type="java.lang.Integer" index="0"></constructor-arg> <constructor-arg name="cname" value="保时捷" type="java.lang.String" index="1"></constructor-arg> </bean>
<bean id = "user1" class = "com.couture.pojo.User"> <constructor-arg name="id" value="1001" index="0"></constructor-arg> <constructor-arg name="name" value="张三" index="1"></constructor-arg> <constructor-arg name="password" value="123" index="2"></constructor-arg> <constructor-arg name="car" ref="firstCar" index="3"></constructor-arg> </bean>
<bean id = "user2" class = "com.couture.pojo.User"> <constructor-arg name="id" value="1002" index="1"></constructor-arg> <constructor-arg name="name" value="李四" index="0"></constructor-arg> <constructor-arg name="password" value="456" index="2"></constructor-arg> <constructor-arg name="car" ref="firstCar" index="3"></constructor-arg> </bean>
</beans>
|
测试
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
| package com.couture.test;
import com.couture.pojo.Car; import com.couture.pojo.User; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
@Test public void testCar() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car = (Car) applicationContext.getBean("firstCar");
System.out.println(car); }
@Test public void testUser() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User user1 = (User) applicationContext.getBean("user1"); System.out.println(user1);
User user2 = (User) applicationContext.getBean("user2"); System.out.println(user2); } }
|
7.4注解注入
注意:需要在applicationContext.xml文件中,导入context约束
Car
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
| package com.couture.pojo;
import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service;
@Component @Data public class Car {
@Value("20001") private Integer cid;
private String cname;
@Value("保时捷") public void setCname(String cname) { this.cname = cname; } }
|
User
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| package com.couture.pojo;
import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.annotation.Resource;
@Component @Scope(value = "singleton") @Data public class User {
@Value("1001") private Integer id;
@Value("张三") private String name;
@Value("123") private String password;
@Autowired @Qualifier("otherCar") private Car car;
@PostConstruct public void init(){ System.out.println("User 初始化"); }
@PreDestroy public void destroy(){ System.out.println("User 销毁"); } }
|
applicationContext.xml配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?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">
<context:component-scan base-package="com.couture"></context:component-scan>
<bean name="otherCar" class="com.couture.pojo.Car"> <property name="cid" value="30001"></property> <property name="cname" value="法拉利"></property> </bean>
</beans>
|
bean.xml
1 2 3 4 5 6 7 8 9 10 11 12 13
| <?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">
<import resource="applicationContext.xml"></import>
</beans>
|
测试
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| package com.couture.test;
import com.couture.pojo.Car; import com.couture.pojo.User; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
@Test public void testCar() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car = (Car) applicationContext.getBean("car");
System.out.println(car); }
@Test public void testUser() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) applicationContext.getBean("user");
System.out.println(user); }
@Test public void testScope() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User user1 = (User) applicationContext.getBean("user"); User user2 = (User) applicationContext.getBean("user");
System.out.println(user1 == user2); }
@Test public void testLife() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
User user = (User) applicationContext.getBean("user"); System.out.println(user);
applicationContext.close(); }
}
|
8.整合MyBatis 【重点】
8.1导入依赖
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| <?xml version="1.0" encoding="UTF-8"?> <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>com.couture</groupId> <artifactId>spring-05</artifactId> <version>1.0-SNAPSHOT</version>
<properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties>
<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.9</version> </dependency>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.29</version> </dependency>
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.9</version> </dependency>
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> </dependency>
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.20</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.20</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.7</version> </dependency>
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency>
</dependencies>
</project>
|
8.2User类
1 2 3 4 5 6 7 8 9 10 11 12
| package com.coutrue.pojo;
import lombok.Data;
@Data public class User {
private Integer id; private String name; private String password;
}
|
8.3UserController
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
| package com.couture.controller;
import com.couture.pojo.User; import com.couture.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller;
import java.util.List;
@Controller public class UserController {
@Autowired private UserService userService;
public List<User> findAll(){ return userService.findAll(); }
}
|
8.4UserService
1 2 3 4 5 6 7 8 9 10 11 12 13
| 01020304050607080910111213package com.couture.service;
import com.couture.pojo.User;
import java.util.List;
public interface UserService {
List<User> findAll(); }
|
8.5UserServiceImpl
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
| package com.qf.service.impl;
import com.coutrue.mapper.UserMapper; import com.coutrue.pojo.User; import com.coutrue.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;
import java.util.List;
@Service public class UserServiceImpl implements UserService {
@Autowired private UserMapper userMapper;
@Override public List<User> findAll() { return userMapper.findAll(); } }
|
8.6UserMapper
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package com.coutrue.mapper;
import com.coutrue.pojo.User; import org.springframework.stereotype.Repository;
import java.util.List;
@Repository public interface UserMapper {
List<User> findAll(); }
|
8.7UserMapper.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
| <?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.coutrue.mapper.UserMapper"> <resultMap id="userMap" type="com.coutrue.pojo.User"> <id property="id" column="id"></id> <result property="name" column="name"></result> <result property="password" column="password"></result> </resultMap> <sql id="baseSql"> select id, name, password from t_user </sql> <select id="findAll" resultMap="userMap"> <include refid="baseSql"></include> </select> </mapper>
|
8.8db.properties
1 2 3 4
| db.username = root db.password = root db.url = jdbc:mysql://localhost:3306/java?serverTimezone=Asia/Shanghai&characterEncoding=UTF8 db.driver = com.mysql.cj.jdbc.Driver
|
8.9log4j.properties
properties
1 2 3 4 5 6
| Global logging configuration log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
|
8.10mybatis-config.xml
1 2 3 4 5 6 7 8 9 10 11 12
| <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration>
<settings> <setting name="logImpl" value="LOG4J"/> </settings>
</configuration>
|
8.11applicationContext.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 34 35 36 37 38 39
| <?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">
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="username" value="${db.username}"></property> <property name="password" value="${db.password}"></property> <property name="url" value="${db.url}"></property> <property name="driverClassName" value="${db.driver}"></property> </bean>
<context:component-scan base-package="com.coutrue"></context:component-scan>
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="datasource"></property> <property name="configLocation" value="classpath:mybatis-config.xml"></property> <property name="mapperLocations" value="classpath:mapper/*.xml"></property> </bean>
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.coutrue.mapper"></property> </bean> </beans>
|
8.12测试
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
| package com.couture.test;
import com.couture.controller.UserController; import com.couture.pojo.User; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class SpringTest {
@Test public void test_findAll(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserController userController = (UserController)applicationContext.getBean("userController");
List<User> userList = userController.findAll();
System.out.println(userList); } }
|
9.数据源配置类
用于替换applicationContext.xml中数据源的相关配置
<context:property-placeholder location=“classpath:db.properties”></context:property-placeholder>
java
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| package com.coture.config;
import com.alibaba.druid.pool.DruidDataSourceFactory; import com.couture.pojo.User; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource; import java.util.Properties;
@Configuration @PropertySource(value = "classpath:db.properties") public class DataSourceConfig {
@Value("${db.username}") private String username;
@Value("${db.password}") private String password;
@Value("${db.url}") private String url;
@Value("${db.driver}") private String driverClassName;
@Bean("datasource") public DataSource getDataSource() { Properties properties = new Properties(); properties.setProperty("username", username); properties.setProperty("password", password); properties.setProperty("url", url); properties.setProperty("driverClassName", driverClassName);
DataSource dataSource = null;
try { dataSource = DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); }
return dataSource; }
}
|
10.分页
10.1导入依赖
1 2 3 4 5
| <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.3.0</version> </dependency>
|
10.2第一种方式在mybatis-config.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
| <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration>
<settings> <setting name="logImpl" value="LOG4J"/> </settings>
<plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <property name="helperDialect" value="mysql"/> <property name="reasonable" value="true"/> <property name="supportMethodsArguments" value="true"/> </plugin> </plugins>
</configuration>
|
10.3第二种方式在applicationContext.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
| <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="datasource"></property> <property name="configLocation" value="classpath:mybatis-config.xml"></property> <property name="mapperLocations" value="classpath:mapper/*.xml"></property>
<property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <value> helperDialect = mysql reasonable = true supportMethodsArguments = true </value> </property> </bean> </array> </property>
</bean>
|
10.4 测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
@Test public void test_findByPage(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserController userController = (UserController)applicationContext.getBean("userController");
PageInfo pageInfo = userController.findByPage(4, 2);
System.out.println(pageInfo.getList()); }
|
9.AOP
Aspect Oriented Programing 面向切面编程
springAOP:在程序运行期通过动态代理的方式向目标类(接口),织入增强的代码,为目标类(接口)中的方法添加额外的功能
采取是横向抽取机制,取代了我们传统的纵向继承方式重复性的代码
底层原理:代理模式
9.1装饰器模式
装饰器模式:对象本身增强
代理模式:代理对象(代理过程)增强
9.1.1Info
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.couture.decorator;
public abstract class Info {
public abstract void info();
}
|
9.1.2PersonInfo
1 2 3 4 5 6 7 8 9 10 11 12
| package com.couture.decorator;
public class PersonInfo extends Info{ @Override public void info() { System.out.println("自我介绍"); } }
|
9.1.3Decorator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package com.couture.decorator;
public abstract class Decorator extends Info{
private Info info;
public Decorator(Info info){ this.info = info; }
@Override public void info() { info.info(); } }
|
9.1.4Singer
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
| package com.couture.decorator;
public class Singer extends Decorator{
public Singer(Info info) { super(info); }
public void singing(){ System.out.println("唱歌"); }
@Override public void info() { super.info(); singing(); } }
|
9.1.5Dancer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package com.couture.decorator;
public class Dancer extends Decorator{
public Dancer(Info info) { super(info); }
public void dancing(){ System.out.println("跳舞"); }
@Override public void info() { super.info(); dancing(); } }
|
9.1.6Magic
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package com.couture.decorator;
public class Magic extends Decorator{
public Magic(Info info) { super(info); }
public void magic(){ System.out.println("变魔术"); }
@Override public void info() { super.info(); magic(); } }
|
9.1.7测试
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
| package com.couture.decorator;
public class Test { public static void main(String[] args) {
Info personInfo = new PersonInfo(); Decorator singer = new Singer(personInfo); Dancer dancer = new Dancer(singer); Magic magic1 = new Magic(dancer); Magic magic2 = new Magic(magic1);
magic2.info(); } }
|
9.2代理模式
通过代理类对象,为目标类对象添加功能
分类:静态代理和动态代理
静态代理:需要实现接口中的方法,进行增强,代理的功能代码有冗余,维护性较差
动态代理:在不实现接口中所有方法,对接口中的指定的方法进行增强
9.2.1静态代理
Rent
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.couture.proxy.demo1;
public interface Rent {
public void rent();
}
|
Owner
1 2 3 4 5 6 7 8 9 10 11
| package com.couture.proxy.demo1;
public class Owner implements Rent{ @Override public void rent() { System.out.println("房东出租房子"); } }
|
OwnerProxy
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
| package com.couture.proxy.demo1;
public class OwnerProxy implements Rent{
private Owner owner;
public OwnerProxy(Owner owner) { this.owner = owner; }
public void publish(){ System.out.println("发布租房信息"); }
public void seeHouse(){ System.out.println("带租户看房子"); }
@Override public void rent() { publish(); owner.rent(); seeHouse(); } }
|
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.couture.proxy.demo1;
public class Test { public static void main(String[] args) {
Owner owner = new Owner(); owner.rent();
System.out.println("----------------");
OwnerProxy ownerProxy = new OwnerProxy(owner); ownerProxy.rent();
} }
|
9.2.2动态代理
分为:JDK动态代理 和 CGLIB动态代理
JDK动态代理:基于接口的动态代理,被代理对象必须实现接口
CGLIB动态代理 :基于子类的动态代理,对目标对象进行继承代理
JDK动态代理
Rent
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.couture.proxy.demo2;
public interface Rent {
public void rent();
public void test(); }
|
Owner
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.couture.proxy.demo2;
public class Owner implements Rent { @Override public void rent() { System.out.println("房东出租房子"); }
@Override public void test() { System.out.println("测试方法"); } }
|
RentJdkProxy
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 48 49 50 51 52 53 54
| package com.couture.proxy.demo2;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public class RentJdkProxy implements InvocationHandler {
private Rent rent;
public void setRent(Rent rent) { this.rent = rent; }
public Rent getRent(){ return (Rent)Proxy.newProxyInstance( rent.getClass().getClassLoader(), rent.getClass().getInterfaces(), this ); }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null;
if("rent".equals(method.getName())){ publish(); result = method.invoke(rent,args); seeHouse(); } else { result = method.invoke(rent,args); }
return result; }
public void publish(){ System.out.println("发布租房信息"); }
public void seeHouse(){ System.out.println("带租户看房子"); } }
|
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package com.couture.proxy.demo2;
public class Test { public static void main(String[] args) {
Owner owner = new Owner(); owner.rent();
System.out.println("-------------------");
RentJdkProxy rentJdkProxy = new RentJdkProxy(); rentJdkProxy.setRent(owner);
Rent proxyRent = rentJdkProxy.getRent(); proxyRent.rent();
proxyRent.test();
} }
|
9.3Spring中的AOP
面向切面编程 (AOP) 通过提供另一种思考程序结构的方式来补充面向对象编程 (OOP),OOP的延伸
对目标对象中的多个不同方法进行不同程度的增强
AOP的术语:
Joinpoint(连接点):所谓连接点是指那些被拦截到的点,在spring中,这些点指的是方法,spring只支持方法类型的连接点。
Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义。
Advice(通知/增强):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知,通知分为前置通知,后置通知,异常通知,最终通知,环绕通知。
Introduction(引介):可以在运行期为类动态地添加一些方法或Field。
Target(目标对象):代理的目标对象。
Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。
Proxy(代理):一个类被AOP织入增强后,就产生一个代理类。
Aspect(切面):是切入点和通知(引介)的结合
9.4XML配置AOP
9.4.1导入依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.20</version> </dependency>
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.9.1</version> </dependency>
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency>
</dependencies>
|
9.4.2UserService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.couture.service;
public interface UserService {
public void add();
public void delete();
public void update();
public void query(); }
|
9.4.3UserServiceImpl
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
| package com.couture.service.impl;
import com.couture.service.UserService;
public class UserServiceImpl implements UserService { @Override public void add() { System.out.println("add"); int i = 1/0; }
@Override public void delete() { System.out.println("delete"); }
@Override public void update() { System.out.println("update"); }
@Override public void query() { System.out.println("query"); } }
|
9.4.4MyAdvice
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
| package com.couture.advice;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAdvice {
public void before(){ System.out.println("前置通知,目标对象调用方法前执行"); }
public void after(){ System.out.println("后置通知(最终通知),目标对象调用方法后执行,无论目标对象方法是否发生异常都会执行"); }
public void after_returning(){ System.out.println("后置通知,目标对象调用方法后执行,目标对象方法发生异常则不执行"); }
public void after_throwing(){ System.out.println("异常通知,目标对象调用方法发生异常时执行"); }
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕通知,目标对象调用方法之前"); proceedingJoinPoint.proceed(); System.out.println("环绕通知,目标对象调用方法之后"); }
}
|
9.4.5applicationContext.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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| <?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" 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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="userService" class="com.coutrue.service.impl.UserServiceImpl"></bean>
<bean id="myAdvice" class="com.coutrue.advice.MyAdvice"></bean>
<aop:config proxy-target-class="true">
<aop:pointcut id="pc" expression="execution(* com.coutrue.service.impl.*ServiceImpl.*(..))"/>
<aop:aspect ref="myAdvice"> <aop:before method="before" pointcut-ref="pc"></aop:before>
<aop:after method="after" pointcut-ref="pc"></aop:after>
<aop:after-returning method="after_returning" pointcut-ref="pc"></aop:after-returning>
<aop:after-throwing method="after_throwing" pointcut-ref="pc"></aop:after-throwing>
<aop:around method="around" pointcut-ref="pc"></aop:around>
</aop:aspect>
</aop:config>
</beans>
|
9.4.6测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package com.couture.test;
import com.couture.service.UserService; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
@Test public void testAop(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService)applicationContext.getBean("userService");
userService.add();
} }
|