Spring
1.本章主要内容
1.Spring框架概要
2.IOC容器
3.AOP
4.JdbcTemplate
5.事务管理
6.Spring5新特性
2.Spring概要
概述
它是一个轻量级的开源的JavaEE框架
轻量级:体积小,依赖的jar包少,并且不需要依赖额外的组件
开源:免费提供源代码
框架:可以简化我们构建框架的过程
目的
为了解决企业级应用的复杂性
核心
IOC:控制反转-把创建对象的过程交给Spring进行管理
AOP:面向切面编程-不修改源码进行功能增强
优点
-
方便解耦,简化开发
-
对AOP编程支持
-
方便程序的测试
-
方便集成整合其他各种的框架
-
方便进行事务操作
-
降低API的开发
3.Spring入门案例
- 先再pojo里创建User实体类
package com.wdzl.pojo;
public class User {
public void showInfo(){
System.out.println("我是User的对象");
}
}
-
再在resource中创建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"> <!-- 创建user对象 --> <bean id="user" class="com.wdzl.pojo.User"></bean> </beans>
-
最后在test里进行测试
import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class UserTest { @Test public void test(){ //1.加载Spring配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); //2.通过获取User对象 User user = context.getBean("user",User.class); user.showInfo(); } }
-
Spring入门案例2
1.创建图书类
public class Book {
private String name;
private String author;
}
2.创建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">
<!-- 创建book对象方式有两种 -->
<!-- <bean id="book" class="com.wdzl.pojo.Book">-->
<!-- <property name="name" value="Java从入门到入土"></property>-->
<!-- <property name="author" value="布莱恩特"></property>-->
<!-- </bean>-->
<bean id="book" class="com.wdzl.pojo.Book">
<!--方式有两种-->
<!-- <constructor-arg name="name" value="Java葵花宝典"></constructor-arg>-->
<!-- <constructor-arg name="author" value="啊giao"></constructor-arg>-->
<constructor-arg index="0" value="Java葵花宝典"></constructor-arg>
<constructor-arg index="1" value="啊giao"></constructor-arg>
</bean>
</beans>
3.test
import com.wdzl.pojo.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BookTest {
@Test
public void test(){
//1.加载配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("beans2.xml");
//2.获取对象
Book book = context.getBean("book", Book.class);
System.out.println(book);
}
}
4.IOC容器
概述
控制反转
控制反转就是把创建对象,和对象间的调用的过程交给Spring来管理。目的是为了降低类与类之间的耦合性
底层原理
- XML解析
- 工厂模式
- 反射
原理图解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FAVq9xSK-1617436140529)(C:\Users\dell\Pictures\java截图\IOC底层原理.jpg)]
几个重要的概念
1.IOC容器:IOC的实现,依赖于IOC容器,而IOC容器的本质就是对象工厂
2.IOC容器的实现
BeanFactory:
-
是最底层的接口,他只提供了最简单的容器功能:加载配置文件 和 创建对象
当加载配置文件时,不会创建被配置的对象,只有在使用时,对象才会创建
-
好处:节省内存
-
坏处:因为在服务器运行的时候去创建对象,会影响执行效率
ApplicationContext:
-
-
应用上下文,他是继承了BeanFactory,它是Spring更高级的一个容器接口,它提供了更多有用的功能
当加载配置文件的时候,会同时创建被配置的 对象
- 好处:效率高,将复杂的创建过程在服务器启动时完成
- 坏处:耗费资源
- ApplicationContext的三个实现类
查看:选中ApplicationContext —》按Ctrl 点击 —》右上角download source(如果有)-----》Ctrl H—》即可查看继承体系结构
ClassPathXmlApplicationContext:从项目中的Sources文件中加载配置文件你
FileSystemXmlApplicationContext:从文件系统读取配置文件(需要访问权限)
AnnotationConfigApplicationContext:读取注解配置
- ApplicationContext的三个实现类
5.IOC操作-Bean管理
概念
IOC 操作-Bean管理是指两个操作:
1.Spring创建对象
2.Spring注入属性(属性赋值)
实现方式
1.XML方式
2.注解方式
5.1.基于XML方式—创建对象
该方式与入门案例方式相同
bean标签的常用属性
id:唯一标识,通过该属性可以找到对应的Bean标签
class:类的全限定类名
注意事项
创建对象时,默认执行无参构造方法来完成对象的创建(反射)
5.2.基于XML—注入属性(属性赋值)
**DI:**依赖注入,它是IOC的一个具体操作
分类
1.使用set方法进行注入
2.使用构造器 进行注入
演示
属性注入通过
name:实体类属性名
value:属性类
p命名空间注入
1.在配置文件中添加一个约束
xmlns:p="http://www.springframework.org/schema/p"
2.注入Bean
<bean id="book" class="com.wdzl.pojo.Book" p:name = "Java入门宝典" p:author="aaa">
</bean>
外部Bean
新建modul,在pom,xml中添加相关依赖
按照三层架构:1.Dao,Service,Web,pojo 2.resource 3.test
定义两个接口
package com.wdzl.service;
public interface UserService {
void addUser();
}
package com.wdzl.dao;
public interface UserDao {
void addUser();
}
在类的同一级定义两个impl下的类
package com.wdzl.dao.impl;
import com.wdzl.dao.UserDao;
public class UserDaoImpl implements UserDao {
@Override
public void addUser() {
System.out.println("我是帅哥");
}
}
import com.wdzl.dao.UserDao;
import com.wdzl.service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao;
@Override
public void addUser() {
userDao.addUser();
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
在xml中添加外部bean
<!-- 创建userDao对象 -->
<bean id="userDao" class="com.wdzl.dao.impl.UserDaoImpl"></bean>
<!-- 配置userservice对象-->
<bean id="userService" class="com.wdzl.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
test
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserService service = context.getBean("userService", UserService.class);
service.addUser();
}
内部Bean
创建两个实体类在pojo中
package com.wdzl.pojo;
public class Dept {
private String deptName;
}
package com.wdzl.pojo;
public class Emp {
private String name;
private String gender;
private Dept dept;
}
<!--内部bean-->
<bean id="emp" class="com.wdzl.pojo.Emp">
<!--基本数据-->
<property name="name" value="周杰伦"></property>
<property name="gender" value="男"></property>
<!--引用数据类型-->
<property name="dept">
<bean id="dept" class="com.wdzl.pojo.Dept">
<property name="deptName" value="研发部"></property>
</bean>
</property>
</bean>
test
@Test
public void innerBeanTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans2.xml");
Emp emp = context.getBean("emp", Emp.class);
System.out.println(emp);
}
级联操作
级联操作方式1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CFnudQMY-1617436140531)(C:\Users\dell\Pictures\java截图\级联操作_LI.jpg)]
级联操作方式2:
<!--将Bean里面的东西,如下,添加到引用数据类型下-->
<property name="dept.deptName" value="研发部"></property>
注意:
针对方式2:
1.一定要在相应的类中添加get,set方法,否则会爆红。
2.同时给两个对象的属性同时赋值。
属性注入
创建实体类
import java.util.List;
import java.util.Map;
public class Demo {
private String[] strings;
private List<String> list;
private Map<String,String> map;
}
xml中完成
<bean id="demo" class="com.wdzl.pojo.Demo">
<!--字符串数组-->
<property name="strings">
<array>
<value>你好</value>
<value>Hello</value>
</array>
</property>
<!--list集合-->
<property name="list">
<list>
<value>Hello</value>
<value>Spring</value>
</list>
</property>
<!--map-->
<property name="map">
<map>
<entry key="Hello" value="你好"></entry>
<entry key="Spring" value="春天"></entry>
</map>
</property>
</bean>
test
@Test
public void arrayMapTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans4.xml");
Demo demo = context.getBean("demo", Demo.class);
System.out.println(demo);
}
引用数据类型
创建实体类
package com.wdzl.pojo;
public class City {
private String cityname;
}
package com.wdzl.pojo;
import java.util.List;
public class Province {
private List<City> cities;
}
配置对象信息
方法一
<!--<bean id="province" class="com.wdzl.pojo.Province">-->
<!-- <property name="cities" >-->
<!-- <list>-->
<!-- <ref bean="city1"></ref>-->
<!-- <ref bean="city2"></ref>-->
<!-- </list>-->
<!-- </property>-->
<!--</bean>-->
<!-- <bean id="city1" class="com.wdzl.pojo.City">-->
<!-- <property name="cityname" value="西安"></property>-->
<!-- </bean>-->
<!-- <bean id="city2" class="com.wdzl.pojo.City">-->
<!-- <property name="cityname" value="延安"></property>-->
<!-- </bean>-->
方法二
<?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: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">
<util:list id="cityList">
<value>西安</value>
<value>延安</value>
<value>宝鸡</value>
</util:list>
<bean id="province" class="com.wdzl.pojo.Province">
<property name="cities" ref="cityList"></property>
</bean>
</beans>
test
@Test
public void arrayMapTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans5.xml");
Province province = context.getBean("province", Province.class);
System.out.println(province);}
FactoryBean
概述
Spring 中有两种类型的Bean,一种是普通的Bean,一种是工厂Bean
- 普通Bean
- 工厂Bean
创建实体类
package com.wdzl.pojo;
import org.springframework.beans.factory.FactoryBean;
public class MyBean implements FactoryBean<String> {
/**
* 返回对象,此方法中真正注入MyBean时返回的对象
* @return
* @throws Exception
*/
@Override
public String getObject() throws Exception {
return "我是字符串";
}
/**
* 返回对象类型
* @return
*/
@Override
public Class<?> getObjectType() {
return null;
}
/**
* 是否是单例
* @return
*/
@Override
public boolean isSingleton() {
return false;
}
}
配置文件
<bean id="myBean" class="com.wdzl.pojo.MyBean"></bean>
test
@Test
public void factoryBeanTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans6.xml");
String myBean = (String)context.getBean("myBean");
System.out.println(myBean);
}
5.3Bean的作用域
概述
在Spring中设置并创建Bean实例是单例还是多例
注意
Singleton和prototype的区别:
1.Singleton:加载配置文件时对象便会创建,并且值创建一个对象
2.prototype:在加载配置文件时并部创建对象,在调用getBean方法时才会创建对象,并且每次调用都会创建。
5.4Bean的生命周期
概述:
一个对象从创建到销毁的过程
过程:
1.通过构造器创建Bean实例
2.为Bean的属性设置值或引用其他Bean(调用set方法)
执行后置处理
3.调用Bean的初始化方法
执行后置处理
4.Bean的对象获取
5.容器关闭,调用Bean的销毁方法
演示
创建实体类
package com.wdzl.pojo;
public class User {
private String name;
}
package com.wdzl.pojo;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* 后置处理类
*/
public class MyBeanLast implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第三步,执行后置处理postProcessBeforeInitialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第五步,执行后置处理postProcessAfterInitialization");
return bean;
}
}
beans.xml
<bean id="user" class="com.wdzl.pojo.User" init-method="init" destroy-method="destroy">
<property name="name" value="周杰伦"></property>
</bean>
<bean id="MyBeanLast" class="com.wdzl.pojo.MyBeanLast"></bean>
test
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = context.getBean("user", User.class);
System.out.println("第六步,获取对象");
((ClassPathXmlApplicationContext)context).close();
}
输出结果:
第一步,通过构造器创建对象
第二步,为Bean的属性设置值
第三步,执行后置处理postProcessBeforeInitialization
第四步,调用初始化方法
第五步,执行后置处理postProcessAfterInitialization
第六步,获取对象
第七步,调用销毁的方法
5.5XML自动装配
概述:
根据指定的装配规则(属性名称,属性类型),Spring自动将匹配的属性注入
实现
借助标签里的autowire属性来实现自动装配,该属性有两个值:
-
byName:根据属性名注入
-
byType:根据属性类注入
如果有多个属性相同的Bean标签,自动装配会报错
5.6引入外部配置文件
<!--引入外部配置文件--> <context:property-placeholder location="jdbc.properties"/> <bean id="dateSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${druid.driverClassName}"></property> <property name="url" value="${druid.url}"></property> <property name="username" value="${druid.username}"></property> <property name="password" value="${druid.password}"></property> </bean>
5.7基于注解方式创建对象
**注解概述:**注解时代码的贴特殊标记
注解格式:@注解名称(属性名=)
**注解应用:**它可以简化XML的配置,注解可以用在类上,属性,方式上
Spring针对创建对象提供了四个注解
-
@Component:普通类使用
-
@Service:Service层使用
-
@Controller:Web层使用
-
@Repository:Dao层使用
这四个注解功能时相同的,都可以用来创建Bean对象
步骤:
导依赖
创建实体类
package com.wdzl.dao;
import org.springframework.stereotype.Repository;
@Repository(value = "userDao")//相当于id属性,括号里的可以写可不写
public class UserDao {
public void addUser(){
System.out.println("UserDao:addUser...");
}
}
配置文件
<!-- 开启组件扫描-->
<context:component-scan base-package="com.wdzl.dao"></context:component-scan>
test
@Test
public void test (){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserDao userDao = context.getBean("userDao", UserDao.class);
userDao.addUser();
}
5.8基于注解方式-属性注入
常用注解
1.@AutoWired:根据属性类型进行注解方式的属性注入
2.@Quailifier
要与AutoWired同时使用
同时使用时为了
6.AOP
概述:
面向切面编程,在不改变源码的情况下对现有程序进行维护
6.1AOP底层原理
**概述:**底层使用了动态代理技术
**分类:**两种情况的动态代理
-
没有接口的情况,使用了CGLIB动态代理
- 通过创建子类对象,在子类中重写方法,并通过super.方法名()调用被代理类中的方法
-
有接口的情况:使用JDK的动态代理
- 代理对象与被代理对象实现相同的接口
6.2AOP相关术语
-
连接点(JoinPoint):类里面那些方法可以被增强,这些方法就叫做连接点
-
切入点(Advice):类中实际被增强的方法,成为切入点
-
通知/增强:
- 前置增强:在调用被增强方法前执行
- 后置增强:在调用被增强方法后执行
- 环绕增强:在调用被增强方法前后都执行
- 异常增强:在调用被增强方法出现异常时执行
- 最终增强:在调用被增强方法后,无论是否出现异常,都会被执行
-
切面(Aspect):切面本身是一个动作,将增强应用到切入点的过程
-
代理(Proxy)
-
目标对象(Target)
-
织入(Weaving)
6.3Aspectj
**概述:**Aspectj
相关依赖
<?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.wdzl</groupId>
<artifactId>07_AOP_anno</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<!--Spring日志依赖-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<!-- junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
</project>
切入点表达式:
**概述:**让Spring框架知道那个类里面的那个方法需要在增强
语法结构
-
execution([权限修饰符])[返回值类型] [全限定类名] ([参数列表])
- 权限修饰符可以省略
- 返回值为*代表任意返回值类型
-
举例
- 对com.wdzl.dao.UserDao类中的addUser方法进行增强
- execution(*com.wdzl.dao.UserDao)
7.JDBCTemplate
**概述:**Spring对JDBC的封装,使用它可以方便的去操作数据库
8.事务
8.1事务环境搭建
新建module
编写配置文件
编写Dao层接口,及相应的实现类
测试
8.2事务操作
-
事务应添加到三层架构中的service层
- 因为Service负责组装业务
-
在Spring中进行事务管理
- 编程式事务
- 声明式事务
-
声明式事务管理
- 基于注解方式
- 基于XML方式
-
在Spring中进行声明式事务管理,使用了AOP
8.3常见事务类型
- propagation :事务传播行为
- isolation: 事务隔离级别
- timeout:超时时间
- readOnly:是否只读
- rollbackFor:回滚
ifactId>cglib
3.3.0
切入点表达式:
**概述:**让Spring框架知道那个类里面的那个方法需要在增强
语法结构
- execution([权限修饰符])[返回值类型] [全限定类名] ([参数列表])
- 权限修饰符可以省略
- 返回值为*代表任意返回值类型
- 举例
- 对com.wdzl.dao.UserDao类中的addUser方法进行增强
- execution(*com.wdzl.dao.UserDao)
## 7.JDBCTemplate
**概述:**Spring对JDBC的封装,使用它可以方便的去操作数据库
## 8.事务
### 8.1事务环境搭建
<font color='cornflowerblue'>新建module</font>
<font color='cornflowerblue'>编写配置文件</font>
<font color='cornflowerblue'>编写Dao层接口,及相应的实现类</font>
<font color='cornflowerblue'>测试</font>
### 8.2事务操作
- 事务应添加到三层架构中的service层
- 因为Service负责组装业务
- 在Spring中进行事务管理
- 编程式事务
- <font color='red'>声明式事务</font>
- 声明式事务管理
- <font color='red'>基于注解方式</font>
- 基于XML方式
- 在Spring中进行声明式事务管理,使用了AOP
### 8.3常见事务类型
\- propagation :事务传播行为
\- isolation: 事务隔离级别
\- timeout:超时时间
\- readOnly:是否只读
\- rollbackFor:回滚
\- noRollbackFor:不回滚