spring 框架入门到精通

1 简介

1.1 核心功能

  1. IOC/DI(控制反转、依赖注入)
  2. AOP(面向切面编程)
  3. 声明式事务

1.2 运行时环境

在这里插入图片描述

1.3 重要概念

1.3.1 容器

Spring是一个大的容器,新版本中ApplicationContext接口,是一个大容器,可以取到Spring中所有的东西
从Spring3开始,把Spring的功能拆分成多个jar包,用什么导入什么jar包

1.3.2 test

Spring提供的单元测试功能

1.3.3 核心容器

Beans:Spring负责管理类对象
Core:核心类
Context:上下文参数,获取外部资源或管理参数
expression:

1.3.4 AOP

AOP:实现aop功能
aspects:aop依赖的包

1.3.5 data access/integration

spring封装数据访问层代码
jdbc:spring对jdbc封装后的代码
orm:封装了一些持久层代码(没有mybaits)
Transactions:声明式事务使用

1.3.6 Web

完成web相关功能时,比如使用tomcat加载配置文件时

2 IOC

控制反转

2.1 定义

原来由程序员由new实例化的任务转交给spring执行
控制:控制类对象
反转:任务转给spring处理
作用:解耦
程序员不需要管理对象了,解除了程序员与对象之间的耦合

2.2 环境搭建

1.导入jar包,包括核心包和日志包
在这里插入图片描述

2.编写applicationContext.xml
文件名称与路径自定义,知识为了记住spring中的容器applicationContext,xml中配置的信息最终存储到了这个容器中
3.配置文件是基于schema的
文件扩展名是.xsd,把schema理解成dtd的升级版,比DTD具备更好的扩展性,每次引入一个xsd文件时

<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">

4.默认配置文件被加载时创建对象

2.3 实战

String[] beanDefinitionNames = ac.getBeanDefinitionNames();
//返回Spring容器管理的所有的对象
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
		People people = ac.getBean("peo",People.class);

2.4 Spring创建对象

2.4.1 无参构造

2.4.2 有参构造

<bean id="peo" class="com.zy.pojo.People">
		<constructor-arg name="name" value="zy"></constructor-arg>
	</bean>

2.4.3 实例工厂

单例设计模式:整个工程只能创建某个类的一个对象
工厂是用来创造对象的,一个工厂可以用来生产多个对象
实例工厂:需要先创建工厂,才能生产对象
在这里插入图片描述
在这里插入图片描述

2.4.4 静态工厂

不需要创建工厂,可以快速创建对象
在这里插入图片描述
把方法变成静态的
在这里插入图片描述

2.5 给Bean的属性赋值(注入)

1、通过构造方法赋值
2、通过set方法赋值
如果属性是基本数据类型或者String等简单数据类型

<bean id="peo2" class="com.zy.pojo.People">
		<property name="name" value="zy2" ></property>
	</bean>

如果属性是set类型等
在这里插入图片描述
list类型
在这里插入图片描述
但是只会赋给一个值
数组
Map
在这里插入图片描述
properties
在这里插入图片描述

2.6 DI

依赖注入
DI和IoC是一样的
当一个类中需要依赖另一个类对象时,为依赖注入
在这里插入图片描述

3 整合mybaits

3.1 步骤

1、导入jar包在这里插入图片描述
2、编写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
    https://www.springframework.org/schema/beans/spring-beans.xsd">
	<!-- 数据源封装类 -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
		<property name="url" value="jdbc:mysql://localhost:3306/ssm?useSSL=false&amp;serverTimezone=UTC"></property>
		<property name="username" value="root"></property>
		<property name="password" value="password"></property>
		<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
	</bean>
	<!-- 创建sqlsessionFactory -->
	<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 扫描后会给相应的接口创建对象 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<!-- 要扫描哪个包 -->
		<property name="basePackage" value="com.zy.mapper"></property>
		<!-- 与factory创建关系 -->
		<property name="sqlSessionFactory" ref="factory" ></property>
	</bean>
	<bean id="airportService" class="com.zy.service.impl.AirportServiceImpl">
		<property name="airportMapper" ref="airportMapper"></property>
	</bean>
</beans>

3、编写代码
正常编写pojo
mapper中必须有接口
正常编写service接口与service实现类,要在实现类总声明mapper接口对象

public class AirportServiceImpl implements AirportService{
	private AirportMapper airportMapper;
	public AirportMapper getAirportMapper() {
		return airportMapper;
	}
	public void setAirportMapper(AirportMapper airportMapper) {
		this.airportMapper = airportMapper;
	}
	@Override
	public List<Airport> selAll() {
		
		return airportMapper.selAll();
	}
}

servlet无法被spring管理
4、整合实例
web.xml中配置监听配置文件

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="4.0" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee           
            http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd">
                                  

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
</web-app>

servlet

package com.zy.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.zy.service.AirportService;
import com.zy.service.impl.AirportServiceImpl;

/**
 * Servlet implementation class AirportServlet
 */
@WebServlet("/AirportServlet")
public class AirportServlet extends HttpServlet {
	AirportService airportService;
	@Override
	public void init() throws ServletException {
		WebApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
		airportService=ac.getBean("airportService",AirportServiceImpl.class);
	}
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setAttribute("list",airportService.selAll() );
		req.getRequestDispatcher("index.jsp").forward(req, resp);
	}
}

4 AOP

4.1 基本概念

面向切面编程
正常程序执行流程都是纵向执行流程
在这里插入图片描述
在原有纵向执行流程中,针对某一个或某一些方法添加通知,形成横切面的过程叫做面向切面编程。
原有功能:切点
前置通知:在切点之前执行的功能(beforeAdvice)
后置通知:在切点之后执行的功能(afterAdvice)
如果切点执行过程中出现异常,会触发异常通知,throws advice
形成切面的过程叫做织入

4.3 schema-based实现aop

每个通知都需要实现接口或类

<bean id="mybefore" class="com.zy.advice.MyBeforeAdvice"></bean>
	<bean id="myafter" class="com.zy.advice.MyAfterAdvice"></bean>
    <aop:config>
    	<aop:pointcut expression="execution(* com.zy.test.Demo.demo2())" id="mypoint"/>
    	<aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"/>
    	<aop:advisor advice-ref="myafter" pointcut-ref="mypoint"/>
    </aop:config>

步骤

1、导入jar包
在这里插入图片描述
2、前置通知

public class MyBeforeAdvice implements MethodBeforeAdvice {
	@Override
	public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
		System.out.println("前置通知");
	}
}

3、后置通知

public class MyAfterAdvice implements AfterReturningAdvice{
	@Override
	public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
		System.out.println("后置通知");
	}
}

4、配置文件

<bean id="mybefore" class="com.zy.advice.MyBeforeAdvice"></bean>
	<bean id="myafter" class="com.zy.advice.MyAfterAdvice"></bean>
    <aop:config>
    	<aop:pointcut expression="execution(* com.zy.test.Demo.demo2())" id="mypoint"/>
    	<aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"/>
    	<aop:advisor advice-ref="myafter" pointcut-ref="mypoint"/>
    </aop:config>

*是通配符,可以匹配任意方法名、任意类名、任意一级包名
如果匹配任意类型参数,(…)
在这里插入图片描述

4.3.2 参数意义

before

public class MyBeforeAdvice implements MethodBeforeAdvice {
	@Override
	public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
		System.out.println("切点方法对象:"+arg0+"方法名"+arg0.getName());
		System.out.println("切点方法参数"+arg1);
		System.out.println("对象"+arg2);
		System.out.println("前置通知");
	}
}

在这里插入图片描述

after

public class MyAfterAdvice implements AfterReturningAdvice{
	@Override
	public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
		System.out.println("返回值"+arg0);
		System.out.println("切点方法对象"+arg1);
		System.out.println("参数"+arg2);
		System.out.println("切点方法所在类的对象"+arg3);
		System.out.println("后置通知");
	}
}

在这里插入图片描述

4.3.3 异常通知

按照特定的要求编写异常通知

4.3.4 环绕通知

1、新建一个类实现MethodInterceptor

package com.zy.advice;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyAround implements MethodInterceptor{
	@Override
	public Object invoke(MethodInvocation arg0) throws Throwable {
		System.out.println("环绕前置");
		Object re = arg0.proceed();
		System.out.println("环绕后置");
		return re;
	}
}	

2、配置文件

 <aop:config>
    	<aop:pointcut expression="execution(* com.zy.test.Demo.demo3(..))" id="mypoint"/>
    	<aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"/>
    	<aop:advisor advice-ref="myafter" pointcut-ref="mypoint"/>
    	<aop:advisor advice-ref="myaround" pointcut-ref="mypoint"/>
    </aop:config>

4.4 AspectJ

4.4.1 配置异常通知的步骤

只有当切点报异常才能触发异常通知

<bean id="mythrow" class="com.zy.advice.MyThrowAdvice"></bean>
    <aop:config>
    	<aop:aspect ref="mythrow">
    		<aop:after-throwing method="myExecption" pointcut-ref="mypoint"/>
    	</aop:aspect>
    </aop:config>
package com.zy.advice;

public class MyThrowAdvice {
   public void myExecption() {
   	System.out.println("异常通知");
   }
}

spring aop 都是拦service异常,一般service都不去try catch
因为无法捕获异常
不需要每个通知实现接口和类

输出异常信息

<aop:after-throwing method="myExecption" pointcut-ref="mypoint" throwing="e"/>
package com.zy.advice;

public class MyThrowAdvice {
	public void myExecption(Exception e) {
		System.out.println("异常通知"+e.getMessage());
	}
}

4.4.2 常用配置

package com.zy.advice;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyAdvice {
	public void mybefore() {
		System.out.println("AspectJ前置");
	}
	public void myafter()
	{
		System.out.println("AspectJ后置");
	}
	public void myaftering()
	{
		System.out.println("AspectJ后置2");
	}
	public void mythrow()
	{
		System.out.println("AspectJ异常");
	}
	public void myaround(ProceedingJoinPoint p) throws Throwable
	{
		System.out.println("aspectJ环绕");
		System.out.println("环绕前置");
		Object proceed = p.proceed();
		System.out.println("环绕后置");
	}
}
<aop:config>
    	<aop:aspect ref="mythrow">
    		<aop:after-throwing method="myExecption" pointcut-ref="mypoint" throwing="e"/>
    	</aop:aspect>
    </aop:config>
    <bean id="myaround" class="com.zy.advice.MyAround"></bean>
    <bean id="myadvice" class="com.zy.advice.MyAdvice"></bean>
    <aop:config>
    	<aop:pointcut expression="execution(* com.zy.test.Demo.demo3(..))" id="mypoint"/>
    	<aop:aspect ref="myadvice">
    		<aop:before method="mybefore" pointcut-ref="mypoint"/>
    		<aop:after method="myafter" pointcut-ref="mypoint"/>
    		<aop:after-returning method="myaftering" pointcut-ref="mypoint"/>
    		<aop:after-throwing method="mythrow" pointcut-ref="mypoint"/>
    		<aop:around method="myaround" pointcut-ref="mypoint"/>
    	</aop:aspect>
    </aop:config>

4.4.3 参数获取

<aop:config>
    	<aop:pointcut expression="execution(* com.zy.test.Demo.demo3(String)) and args(s)" id="mypoint"/>
    	<aop:aspect ref="myadvice">
<!--     		<aop:before method="mybefore" pointcut-ref="mypoint"/> -->
    		<aop:after method="myafter" pointcut-ref="mypoint" arg-names="s"/>
<!--     		<aop:after-returning method="myaftering" pointcut-ref="mypoint"/> -->
<!--     		<aop:after-throwing method="mythrow" pointcut-ref="mypoint"/> -->
<!--     		<aop:around method="myaround" pointcut-ref="mypoint"/> -->
    	</aop:aspect>
    </aop:config>

4.4.4注解方式配置

1、Spring不会自动去找注解,必须告诉spring哪些包下有注解

<context:component-scan base-package="com.zy.advice"></context:component-scan>

引入

<?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
   https://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/aop
   https://www.springframework.org/schema/aop/spring-aop.xsd
   http://www.springframework.org/schema/context
   https://www.springframework.org/schema/context/spring-context.xsd">
   <context:component-scan base-package="com.zy.advice">

2、@Component
相当于bean
默认将首字母变小写
在这里插入图片描述

@Component
public class Demo {
	public void demo1(){
		System.out.println("demo1");
	}

3、在方法上添加pointcut

@Pointcut("execution(* com.zy.test.Demo.demo2())")
	public void demo2() {
		System.out.println("demo2");
	}

定义切点
4、在通知类中配置

@Component
@Aspect
public class MyAdvice {
	@Before("com.zy.test.Demo.demo2()")
	public void mybefore() {
		System.out.println("前置");
	}
}

@Component被spring管理
@Aspect表示是一个切面

4.5 静态代理

设计模式:之前总结的一套解决特定问题的代码
代理设计模式
真实对象:老总
代理对象:秘书
抽象对象(抽象功能):面试
优点:
1、保护真实对象
2、让真实对象职责更加明确
3、扩展
静态代理:
自己编写代理类
每一个代理的功能需要自己编写
缺点:
当代理功能比较多时,代理类中方法也需要写很多

4.6 动态代理

为了解决静态代理需要频繁编写代理功能的缺点
JDK
cglib动态代理

4.6.1 JDK

优点:自带,不需要额外导入第三方jar
缺点:真实对象必须实现接口;利用的反射机制,效率不高
在这里插入图片描述
在这里插入图片描述

4.6.2 cglib

基于字节码机制,生成真实对象的子类
运行效率很高
不需要实现接口
AOP拦截的是被spring管理的方法,fliter拦截的是请求

5 自动注入

spring配置文件中,对象名和ref的id名相同,这种情况下可以使用自动注入,不用配置property
在这里插入图片描述

在这里插入图片描述

6 加载外部属性

1、在src下新建一个properties文件
在spring配置文件中引入
2、

<context:property-placeholder location="classpath:db.properties,classpath:te.properties"/>

在这里插入图片描述

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.zy.mapper"></property>
		<property name="sqlSessionFactoryBeanName" value="factory"></property>
	</bean>

4、
在这里插入图片描述

	@Value("${te}")
	private String te;

7 Scope属性

控制对象的有效范围(单例、多例)
bean标签对应的对象默认是单例的
在这里插入图片描述

8 单例设计模式

提升运行效率
实现数据共享。案例:application对象
在应用程序中最多有一个实例
1、提高运行效率
2、实现数据共享

8.1 懒汉式

对象被调用时才被创建

package com.zy.pojo;

public class SingleTon {
	//必须是private,禁止可以直接访问
	private static SingleTon singleton;
	private SingleTon() {
		
	}
	/**
	 * 为了让类可以直接调用
	 * 防止多线程重复访问
	 * 采用双重验证
	 * @return
	 */
	public static SingleTon getSingleTon() {
		if(singleton==null) {
			synchronized (SingleTon.class) {
				if(singleton==null) {
					singleton=new SingleTon();
				}
			}
		}
		return singleton;
	}
}

8.2 饿汉式

由于添加了锁,导致低效率
解决了懒汉式中多线程访问可能出现同一个对象效率低的问题
在这里插入图片描述

9 声明式事务

9.1 编程式事务

由程序员来编写事务控制代码
OpenSessionInView

9.2 声明式事务

事务控制代码
Spring已经写好代码,程序员只需要声明哪些方法需要进行事务控制和如何进行事务控制。
声明式事务都是针对ServiceImpl类下方法的
事务管理器是基于通知(advice)的
配置文件

<?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"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/aop
	https://www.springframework.org/schema/aop/spring-aop.xsd
	http://www.springframework.org/schema/context
	https://www.springframework.org/schema/context/spring-context.xsd
	http://www.springframework.org/schema/tx
	https://www.springframework.org/schema/tx/spring-tx.xsd">
	<bean id="peo" class="com.zy.pojo.People" scope="singleton"></bean>
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="ins*"/>
		</tx:attributes>
	</tx:advice>
	<aop:config>
		<aop:pointcut expression="execution(* com.zy.service.impl.*.*(..))" id="mypoint"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="mypoint"/>
	</aop:config>
	<context:property-placeholder location="classpath:db.properties,classpath:te.properties"/>
	<context:component-scan base-package="com.zy.service.impl.UsersServiceImpl"></context:component-scan>
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="url" value="jdbc:mysql://localhost:3306/ssm?useSSL=false&amp;serverTimezone=UTC"></property>
		<property name="username" value="root"></property>
		<property name="password" value="password"></property>
		<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
	</bean>
	<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean" >
		<property name="dataSource" ref="dataSource"></property>
		<property name="typeAliasesPackage" value="com.zy.pojo"></property>
	</bean>
</beans>

9.3 属性解释

name=“”表示哪些方法需要有事务控制

9.3.1readonly

=“true”是否为只读事务
如果为true,为只读事务。是数据库优化,会对性能有一定提升
所以只要是查询方法,建议使用此属性
如果为false(默认),比如增删改等
在这里插入图片描述

9.3.2 propagation

控制事务传播行为
当一个具有事务控制的方法被另一个有事务控制的方法调用后,需要如何管理事务(新建事务,在事务中执行,把事务挂起,报异常)
在这里插入图片描述
在这里插入图片描述

9.4 事务隔离级别

在并发访问下,如何保证访问到的数据具有完整性

9.4.1 脏读

一个事务读取到另一个事务中未提交的数据,另一个事务的数据可能进行了改变,此时A事务读取的数据可能和数据库中数据时不一致的,此时认为数据时脏数据,这个过程叫做脏读

9.4.2 不可重复读

主要针对的是某行数据(或行中某列)
主要针对的操作是修改操作
两次读取在同一个事务内
当事务A在第一次读取事务后,事务B对事务A读取的数据进行修改,事务A再次读取的数据和之前读取的数据不一致,叫做不可重复读。
锁行

9.4.3 幻读

针对的操作是新增或者删除
两次事务的结果
事务A按照特定条件查询出了结果,事务B新增了一条符合条件的数据,事务A查询出的数据与数据库中的数据不一致,这种情况为幻读
锁表

9.4.4 isotation

1、default
默认值,由底层数据库自动判断隔离级别
2、READ_UNCOMMITED
可以读取未提交数据,出现脏读、、、但效率最高
3、READ_COMMITED
只能读取其它事务中已提交数据,可以防止脏读,可能出现幻读、不可重复读
4、REPEATABLE——READ
读取的数据枷锁,防止其它事务修改次数据,可以防止不可重复读
5、SERIALIZABLE
排队操作,锁表,一个数据操作时,另一个事务等待操作完成后才能操作此表,最安全的,效率最低的
在这里插入图片描述

9.4.5 事务回滚

在这里插入图片描述
当出现什么异常时,需要进行回滚,建议给定该属性值
当我们手动抛异常时,一定给该属性值

10 常用注解

@Compent
创建类对象,,相当于配置

@Service
与@Compent功能相同,写在ServiceImpl上
Repository
与@Compent功能相同
写在数据访问层上
@Controller
与@Compent功能相同
写在控制器类上
@Resource
jdk的注解
默认按照byName进行注入
如果没有,按照byType注入
不需要写get、set方法
AutoWired
Spring的注解
默认按照byType注入
@Value
获取属性文件中的内容
在这里插入图片描述

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页