文章目录
- Spring5框架
- Springde的基本概述
- Spring是什么
- Spring有核心的部分:IOC和Aop
- Spring 特点
- 入门案例
- 下载spring
- 百度搜索 Spring.io
- 下载地址:
- 点击你所要下载的版本
- 下载第一个链接 (spring-5.3.9-dist.zip)
- Ioc容器
- IOC概念
- ioc底层原理
- 原始方法
- 用工厂模式进行优化
- 了解工厂模式:
- **IOC方法**
- xml解析
- 反射
- IOC(接口)
- Spring提供了IOC容器实现的两种方式:(两个接口)
- ApplicationContext接口中的实现类
- IOC操作Bean管理
- 什么是bean管理
- bean管理操作的两种方式
- 基于xml配置文件方式实现
- 向属性中设置一个空值:
- 向属性中设置特殊符号
- 注入属性-外部bean
- 注入属性 - 内部bean
- IOC操作Bean管理(xml注入集合属性)
- 注入数组类型,list集合类型,Map集合类型的属性
- 如果要把对象作为值进行注入的情况:
- 把注入的过程提取出来
- IOC操作Bean管理(FactoryBean)
- IOC操作Bean管理(bean作用域)
- IOC操作Bean管理(bean生命周期)
- bean的后置处理器(加上后有七步)
- 演示添加后置处理器的效果
- IOC操作Bean管理(xml自动装配)
- ioc操作Bean管理(基于注解方式)
- 开启组件扫描细节
- 基于注解方式实现属性注入
- 全注解配置
- Aop
- 什么是AOP
- Aop底层原理
- 动态代理(两种情况)
- Aop(JDK动态代理)
- Aop操作术语
- Aop操作:
- 什么是AspectJ
- 基于AspectJ实行Aop操作
- 在Aop中引入相关依赖
- 切入点表达式
- AOP操作(AspectJ注解)
- Aop操作(AspectJ配置文件)
- jdbcTemplate(概念和准备)
- 什么是jdbcTemplate
- 准备工作
- jdbcTemplate操作数据库(添加)
- jdbcTemplate操作数据库(批量操作)
- Spring中进行事务管理操作
- 声明式事务管理
- 在spring进行声明式事务管理,底层使用的是Aop原理
- spring事务管理ApI
- 事务操作(注解方式实现声明式事务管理)
- 事务操作(声明式事务管理参数配置)
- Spring5的一些新的功能
- Spring新功能(Webflux)
- Webflux特点
- 比较springMVC
Spring5框架
Springde的基本概述
Spring是什么
spring是轻量级的开源的javaEE框架,目的是解决企业应用开发的复杂性。
spring5框架图:
Spring有核心的部分:IOC和Aop
- IOC:控制反转,把创建对象的过程交给Spring进行管理
- AOP: 面向切面,不修改源代码的情况下,进行功能增强
Spring 特点
- 方便解耦,简化开发
- Aop编程支持
- 方便程序测试
- 方便和其他框架进行整合
- 降低JavaEE api开发难度
- 方便进行事务的操作
入门案例
下载spring
百度搜索 Spring.io
SHAPSHOT是快照版,GA是稳定版的,我们只需要下载最新版的GA版本即可。
下载地址:
https://repo.spring.io/release/org/springframework/spring/
点击你所要下载的版本
下载第一个链接 (spring-5.3.9-dist.zip)
Ioc容器
IOC概念
官方解释:ioc是控制反转,是面向对象编程的一种设计原则,可以用来降低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入,还有一种方式叫做依赖查询。通过控制反转,对象在被创建的时候,有一个调控系统内所有对象的外界实体将其依赖的对象的引用传递给他。也可以说是依赖被注入到对象中。
控制反转:就是把对象创建和对象之间的调用关系全部交给Spring来进行管理。
ioc底层原理
- xml解析
- 工厂模式
- 反射
解释:
原始方法
如图所示:我要实现的功能是通过UserService类中的execute()方法来调用userdao类里面的add()方法,但是这样有一个致命的缺点:耦合度太高了,我们做程序要要求高内聚,低耦合,而显然这样的程序不满足我们的要求。
用工厂模式进行优化
了解工厂模式:
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
**意图:**定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
**主要解决:**主要解决接口选择的问题。
**何时使用:**我们明确地计划不同条件下创建不同实例时。
**如何解决:**让其子类实现工厂接口,返回的也是一个抽象的产品。
**关键代码:**创建过程在其子类执行。
应用实例: 1、您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。 2、Hibernate 换数据库只需换方言和驱动就可以。
优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。
**缺点:**每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
**注意事项:**作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
这样耦合度还是有点高,我们还可以进一步降低
我们用ioc进行进一步的解耦
IOC方法
首先我们需要了解什么是xml解析,什么是反射
xml解析
反射
**第一步:**xml配置文件,配置创建的对象,如
<bean id ="" class=""></bean>
**第二步:**由service类和dao类,创建工厂类
class UserFactory{
public static UserDao getDao(){
String classValue = classs属性值//xml解析
Class clazz = Class.forName(classvalue);
return (UserDao)clazz.newInstance();
}
}
IOC(接口)
IOC思想基于Ioc容器完成的,Ioc容器底层就是对象工厂
Spring提供了IOC容器实现的两种方式:(两个接口)
- BeanFactory:
- IOC容器基本的实现方式,是Spring内部使用的使用的接口,不提供开发人员使用
- 加载配置文件的时候不会创建对象,在获取对象(使用)才去创建对象
- ApplicationContext:
- BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用
- 加载配置文件的时候就会把配置文件对象进行创建
两种方式相比 ,ApplicationContext方法会更好一些,框架最终是要和web项目相结合,因此我们更希望的是在创建项目的时候把所有的耗时好资源的工作都给做完,而不是创建后,操作时完成这些工作。
ApplicationContext接口中的实现类
IOC操作Bean管理
什么是bean管理
- Spring创建对象
- Spring注入属性
bean管理操作的两种方式
基于xml配置文件方式实现
- 基于xml方式创建对象
<bean id ="user" class = "包名.类名"></bean>
- 在这个Spring配置文件中,使用bean标签,标签中添加相应的属性,就可以实现对象创建
- bean标签中由很多属性,常用的有
- id属性:给对象起一个别名,唯一标识
- class:类全路径(包类路径)
- name属性:和id差不多
- 创建对象时,默认也是执行无参的构造方法,完成对象的创建
- 基于xml方式注入属性
- DI是IOC中的一种具体实现,他表示依赖注入,(就是注入属性)
- set方法注入
- 创建类,定义属性和set方法
- 在spring配置文件配置对象,配置属性注入
<bean id = "book" class = "com.wu.book">
<!--使用property完成属性注入
name:类里面的属性名称
value:向属性注入的值
-->
<property name ="bname" value = "易筋经"></property>
<property name = "bauthor" value = "dama"></property>
</bean>
测试:
public void textBook(){
ApplicationContext context =
new ClassPathXmlApplicationContext(configLocation:"beanl.xml");
//获取配置创建对象
Book book = context.getBean("book",Book.class);
book.testDemo();
}
- 有参构造方法注入
public class Orders{
private String oname;
private String address;
public Orders(String oname,String address){
this.oname= oname;
this.address = address;
}
}
在spring配置文件中进行配置:
<bean id = "orders" class = "com.at.spring5.0">
<constructor-arg name = "oname" value ="电脑"></constructor-arg>
<constructor-arg name = "address" value ="China"></constructor-arg>
</bean>
向属性中设置一个空值:
```html
<bean id = "book" class = "com.wu.book">
<!--使用property完成属性注入
name:类里面的属性名称
value:向属性注入的值
-->
<!--向属性里面设置空值-->
<property name = "bauthor" >
<null/>
</property>
</bean>
```
向属性中设置特殊符号
有两种方式:
- 把这个特殊符号进行转义。
- 把带特殊符号内容写到CDATA里面。
<!--要输入《南京》-->
<property name = "address">
<value><![CDATA[《南京》]]></value>
</property>
注入属性-外部bean
- 创建两个类 service类和dao类
//创建一个service类
public class Service{
public void add(){
System.out.println("service add......");
}
}
//创建一个dao接口
public interface Dao{
public void update();
}
//创建一个UserDao类来继承Dao类
public class UserDao implements Dao{
public void update(){
System.out.println("dao update......");
}
}
- 在service中调用dao里面的方法
public class Service{
//创建dao类型属性,生成set方法
private UsrDao userDao;
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
public void add(){
System.out.println("service add......");
userDao.update();
}
}
- 在spring配置文件中进行配置
<!--创建bean.xml
创建service和userdao的bean对象-->
<bean id = "userService" class= "service所在的类位置">
<property name="userDao" ref="userDao"></property>
<!--因为注入的是对象,所以不能用value,应该改成ref,
name属性值:类里面属性名称
ref属性:创建userDao对象bean标签id值
-->
</bean>
<bean id = "userDao" class = "userdao所在的类位置"></bean>
注入属性 - 内部bean
<!--还是上面那个例子
创建service和dao类,和在service中调入dao方法和上面一样,参考上面就行
下面演示一下在spring配置文件里面的不同
-->
<bean id = "userService" class= "service所在的类位置">
<property name = "userDao">
<bean id = "userDao" calss ="userdao类的路径"></bean>
</property>
</bean>
IOC操作Bean管理(xml注入集合属性)
注入数组类型,list集合类型,Map集合类型的属性
- 创建一个Stu类,里面定义数组,list,map,set类型
public class Stu{
//数组类型属性
private String[] courses;
//list集合类型属性
private List<String>list;
//map集合类型属性
private Map<String,String>Maps;
//set集合类型属性
private Set<String>sets;
public void setSets(Set<String>sets){
this.sets = sets;
}
public void setCourses(String[] courses){
this.courses = courses;
}
public void setList(List<String>List){
this.list = list;
}
public void setMaps(Map<String,String>Maps){
this.maps = maps;
}
}
//测试方法
pubic void test(){
System.out.println(Arrays.toString(courses));
System.out.println(list);
System.out.println(maps);
System.out.println(sets);
}
- 在spring配置文件中完成注入
<bean id = "stu" class = "类的路径">
<!--数组类型属性注入-->
<property name = "courses">
<array>
<value></value>
<value></value>
<value></value>
</array>
</property>
<!--list类型属性注入-->
<property name = "list">
<list>
<value></value>
<value></value>
<value></value>
</list>
</property>
<!--map类型属性注入-->
<property name = "map">
<map>
<entry key=" " value=" "></entry>
<entry key=" " value=" "></entry>
<entry key=" " value=" "></entry>
</map>
</property>
<!--set类型属性注入-->
<property name = "sets">
<set>
<value></value>
<value></value>
<value></value>
</set>
</property>
</bean>
- 写一个测试类
pubic void testCollection(){
ApplicationContext context =
new ClassPathXmlApplicationContext(configLocation: "bean.xml");
Stu stu = context.getBean("stu",Stu.class);
stu.test();
}
如果要把对象作为值进行注入的情况:
public class Course{
private String cname;
private List<Course> courseList;
public void setCourseList(List<Course> courseList){
this.courseList = courseList;
}
public void setname(String name){
this.cname = name;
}
}
<!--bean.xml文件进行配置
注入list集合类型,但是类型是对象
-->
<property name = "courseList">
<list>
<ref bean=" course1"></ref>
<ref bean=" course2"></ref>
</list>
</property>
<!--创建多个course-->
<bean id="course1" class="路径">
<property name = "cname" value="spring5"></property>
</bean>
<bean id="course2" class="路径">
<property name = "cname" value="spring5"></property>
</bean>
把注入的过程提取出来
- 把spring配置文件中引入名称空间
改后
注意观察形式的变化。。
- 使用util标签完成list集合注入提取
<!--在改完后的文件中·
在上面例子的基础上
提取list集合类型属性注入
-->
<util:list id ="booklist">
<value>java</value>
<value>c</value>
<value>golang</value>
</util:list>
<!--提取list集合类型属性注入使用-->
<bean id ="book" class = "路径">
<property name = "list" ref = "bookList"></property>
</bean>
IOC操作Bean管理(FactoryBean)
- Spring有两种类型Bean,一种普通bean,另一种为工厂bean(FactoryBean)
1.普通bean:在配置文件中定义bean就是返回类型
2.工厂bean:在配置文件定义bean类型可以和返回类型不一样 - 工厂bean的配置过程:
第一步:创建类,让这个类作为工厂bean,实现接口FactoryBean
第二步:实现接口里面的方法,在实现的方法中定义返回bean类型
public class myBean implements FactroyBean{
@Override
//定义你返回的bean类型
public Object getObject() throws Exception{
ruturn null;
}
@Override
public Class<?>getObjectType(){
return null;
}
@Override
public Class<?>getObjectType(){
return null;
}
}
IOC操作Bean管理(bean作用域)
- 作用域的大小,可以在spring里设置创建bean实例是单实例还是多实例
- 在Spring中,默认情况下时创建的时单实例 (验证方法:可以创建多个bean对象,然后输出,会发现他们输出的地址是一样的)
- 如何让设置一个实例时单实例还是多实例。
- 在spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例
- scope属性值
- 第一个值 默认值,singleton,表示是单实例对象
- 第二个值prototype,表示是多实例对象
- 写的位置
<bean id = "book" class = "包类路径" scope="prototype/singleton"></bean>
- singleton和prototype区别
- singleton单实例,prototype多实例
- 设置scope值是singleton时候,加载spring配置文件 就会创建一个单实例的对象
- 设置值为prototype时候,不是在加载spring配置文件时候创建,在调用getBean方法时候创建多实例对象
IOC操作Bean管理(bean生命周期)
生命周期:从对象创建到对象销毁的过程
bean的生命周期:
- 通过构造器创建bean实例(无参构造器)
- 为bean的属性设置值和对其他bean的引用(调用set方法)
- 调用bean的初始化的方法(需要进行配置)
- bean可以使用了(对象获取到了)
- 当容器关闭的时候,调用bean的销毁的方法(需要自己配置销毁的方法)
演示bean的生命周期:
public class Orders{
//无参数构造器
public Orders(){
System.out.println("第一步 执行无参数构造器创建bean实例");
}
private String oname;
public void setOname(Stirng oname){
this.oname = oname;
System.out.println("第二步 调用set方法设置属性值");
}
//创建执行的初始化的方法
public void initMethod(){
System.out.println("第三步 执行初始化的方法");
}
//创建执行的销毁的方法
public void destoryMethod(){
System.out.println("第五步 执行销毁的方法");
}
}
//测试类
public class test{
public void testBean(){
ApplicationContext context =
new ClassPathXmlApplicationContext(configLocation:"bean4.xml");
Orders orders = context.getBean("orders",Orders.class);
System.out.println("第四步 获取创建bean实例对象");
//手动销毁bean
context.close();
}
}
<bean id ="orders" class = "包类路径" init-method = "initMethod" destroy-method = "destoryMethod">
<property name= "oname" value="手机"></property>
</bean>
bean的后置处理器(加上后有七步)
- 通过构造器创建bean实例(无参构造器)
- 为bean的属性设置值和对其他bean的引用(调用set方法)
- 把bean实例传递bean后置处理器的方法(postProcessBeforeInitialization)
- 调用bean的初始化的方法(需要进行配置)
- 把bean实例传递bean后置处理器的方法(postProcessAfterInitialization)
- bean可以使用了(对象获取到了)
- 当容器关闭的时候,调用bean的销毁的方法(需要自己配置销毁的方法)
演示添加后置处理器的效果
public class MyBeanPost implements BeanPostProcessor{
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException{
return bean;
}
@Override
public Object postProcessAfterInitialization(Objeceet bean, String beanName) throws BeansException{
return bean;
}
}
<!--在配置文件中配置后置处理器-->
<bean id ="MyBeanPost" class="包类路径"></bean>
<!--因为实现了BeanPost接口,运行时会被识别为后置处理器-->
IOC操作Bean管理(xml自动装配)
自动装配:根据指定装配规则(属性名称或属性类型),spring自动将匹配的属性进行注入。
<!--实现自动装配
bean标签属性autowire,配置自动装配
autowire属性常用的两个值:
byName根据属性名称注入,**注入值bean的id值和类属性名称一样**
byType根据类型进行注入
-->
<!--根据名称进行注入-->
<bean id ="emp" class = "包类路径" autowire ="byName"></bea0n>
<!--根据类型进行注入
注意:用这种方式的时候有一些问题:不能在bean文件中配置相同的类型,
-->
<bean id ="emp" class = "包类路径" autowire ="byType">
<!--<property name = "dept" ref ="dept"></property>-->
</bean>
<bean id = "dept" class = "Dept的包类路径"></bean>
<bean id = "dept1" class = "Dept的包类路径"></bean>
<!--这种情况就会报错。因为用类型进行自动装配,有两个一样的bean对象-->
ioc操作Bean管理(基于注解方式)
注解:代码里面特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值…)
- 注解目的:简化xml配置,使用更简洁更优雅的方式进行配置
- Spring针对Bean管理中创建对象提供直接
- @Component
- @Service
- @Controller
- @Repository
上面四个注解功能是一样的,都可以用来创建bean实例
- 基于注解方式实现对象创建
- 引入依赖
- 开启组件扫描
- 配置名称空间(上面有介绍,这里不再赘述)
<!--开启组件扫描
1.如果扫描多个包,多个包使用逗号隔开
2.扫描包上层目录-->
<context:component-scan base-package="com.atguigu"></context:component-scan>
- 创建类,在类上面添加创建对象注解
@Component(value = "userService")
public class UserService{
public void add(){
System.out.println("service add....");
}
}
//其中@Component (value = "userService")等价于<bean id ="userService" class="...">
//不写默认是类名首字母小写的字符串
开启组件扫描细节
<!--实例一
use-default- filters= "false" 表示现在不使用默认filter,自己配置filter
context:include-filter,设置扫描那些内容
-->
<context:component-scan base-package="com.atguigu" use-default-filter="false">
<context:include-filter type = "annotation"
expression ="org.springframework.stereotype.Controller" >
</context:component-scan>
//这段代码意思是选定有Controller注解的进行扫描
<!--实例二
context:exclude-filter:设置那些内容不进行扫描
-->
<context:component-scan base-package="com.atguigu" use-default-filter="false">
<context:exclude-filter type = "annotation"
expression ="org.springframework.stereotype.Controller" >
</context:component-scan>
基于注解方式实现属性注入
- @AutoWired: 根据属性类型进行自动装配
步骤:
1. 把service和dao对象创建,在service和dao类添加创建对象注解
2. 把service 注入dao对象,在service类添加dao类型属性,在属性上使用注解
@Service
public class UserService{
//定义dao类型属性
//不需要添加set方法
//添加注入属性注解
@Autowired
private UserDao userDao;
public void add(){
System.out.println("service add...");
userdao.add();
}
}
//userdao类
@Repository
public class Userdao{
public void add(){
System.out.println("dao add..");
}
}
- @Qualifier:根据属性名称进行注入
@qualifier在使用的时候,要和Autowried一起使用
public class UserService{
//定义dao类型属性
//不需要添加set方法
//添加注入属性注解
@Autowired
@Qualifier(Value= "userDao1")
private UserDao userDao;
public void add(){
System.out.println("service add...");
userdao.add();
}
}
//userdao类
@Repository(value = "userDao1")
public class Userdao implement Dao{
public void add(){
System.out.println("dao add..");
}
}
public interface Dao{
public void add();
}
- @Resource:可以根据类型注入,也可以根据名称注入
- 如果要类型注入直接写@Resource
- 如果要名称注入则这样写@Resource(name = " ")
全注解配置
以上所讲的方法中要使用注解进行配置,需要开启组件扫描
<context:component-scan base-package="com.atguigu"></context:component-scan>
- 创建配置类,用它替代xml的配置文件
要想让类被识别为配置类需要加一个注解:@Configuration,替代xml的配置文件 - @ComponentScan(basePackages = {“com.arguigu”}}等价于
<context:component-scan base-package="com.atguigu"></context:component-scan>
- 编写测试类
public class test{
public void testBean(){
ApplicationContext context =
new AnnotationConfigApplicationContext(SpringConfig.class);
Orders orders = context.getBean("orders",Orders.class);
System.out.println("第四步 获取创建bean实例对象");
//手动销毁bean
context.close();
}
}
Aop
什么是AOP
AOP --------Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP通俗解释: 不通过修改源代码方式,在主干功能里面添加新功能(用登录例子图解来解释)
Aop底层原理
动态代理(两种情况)
- 有接口情况,使用jDK动态代理
创建接口实现类代理对象,增强类的方法 - 没有接口,使用CGILIB动态代理
Aop(JDK动态代理)
- 使用jdk动态代理,使用Proxy类里面的方法来创建代理对象
方法里面三个参数:
- 第一个参数:类加载器
- 第二个参数:增强方法所在的类,这个类实现的接口,支持多个接口
- 第三个参数:实现这个接口InvocationHandler,创建代理对象,写增强的方法
2.编写JDK动态代理代码
- 创建接口,定义方法
public interface UserDao{
public int add(int a, int b);
public String updata(String id);
}
- 创建接口实现类,实现方法
public class UserDaoImp implements UserDao{
@Override
public int add(int a ,int b){
return a+b;
}
@Override
public String updata(String id){
ruturn id;
}
}
- 使用Proxy类创建接口代理对象
public class JDKProxy{
public static void main (String[] args){
Class[] interfaces = {UserDao.class};
UserDaoImp userdao = new UserDaoImp();
UserDao dao = (UserDao)Proxy.newProxyInstance(JDKProxy.class.getClassLoader(),interfaces,new UserDaoProxy(userdao));
int result = dao.add(1,2);
}
}
//创建代理对象代码
class UserDaoProxy implements InvocationHandler{
//有参数的构造传递
private Object obj;
public UserDaoProxy(Object obj){ //直接写UserDaoImp obj也可以
this.obj = obj;
}
//增强的逻辑
public Object invoke(Object proxy,Method method, Object[] args) throws Throwable{
//方法之前
System.out.println("方法之前执行、、、"+metod.getName()+"传递的参数、、、"+Arrays.toString(args));
//被增强的方法执行
Object res = method.invoke(obj,args);
//方法之后
System.out.println("方法之后执行、、、"+obj);
return res;
}
}
Aop操作术语
连接点:类里面哪些方法可以被增强,这些方法被称为连接点
切入点:实际被真正增强的方法,称为切入点
通知(增强):实际增强的逻辑部分称为通知(增强)
- 通知的类型:
- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知
切面:把通知应用到切入点的过程(是动作)
Aop操作:
Spring一般都是基于AspectJ来实现Aop操作的
什么是AspectJ
AspectJ不是spring的组成部分,独立于Aop框架,一般把AspectJ和spring框架一起使用,进行Aop操作
基于AspectJ实行Aop操作
- 基于xml配置文件实现
- 基于注解方式实现(比较常见)
在Aop中引入相关依赖
切入点表达式
- 切入点表达式作用:知道对那个类里面那个方法进行增强
- 语言结构:execution([权限修饰符][返回类型][包全路径][方法名]([参数列表]))
其中*代表所有有效
AOP操作(AspectJ注解)
- 创建类,在类里面定义方法
//被增强类
public class User{
public void add(){
System.out.println("add....");
}
}
- 创建增强类(编写增强逻辑)
- 在增强类里面,创建方法,让不同的方法代表不同的通知类型
//增强的类
public class UserProxy{
//前置通知
public void before(){
system.out .println(before...)
}
}
- 进行通知的配置
- 在spring配置文件中,开启注解扫描
开启名称空间:开启扫描
<context:component- scan base-package= "包类路径"></context:component-scan>
- 使用注解创建User和UserProxy对象
//被增强类
@Component
public class User{
public void add(){
System.out.println("add....");
}
}
//增强的类
@Component
public class UserProxy{
//前置通知
public void before(){
system.out .println(before...)
}
}
- 在增强类中添加注解@Aspect
//增强的类
@Component
@Aspect //生成代理对象
public class UserProxy{
......
}
- 在Spring配置文件中开启生成代理对象
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
- 配置不同类型的通知
- 在增强类里,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
//增强的类
@Component
public class UserProxy{
//前置通知
/*
*加上前置通知注解
*/
@Before(value = "execution([权限修饰符][返回类型][包全路径][方法名]([参数列表])")
public void before(){
system.out .println(before...)
}
}
- 相同的切入点抽取
//相同切入点抽取
@pointcut(value = "execution([权限修饰符][返回类型][包全路径][方法名]([参数列表]")
public void pointdemo(){}
//通过@pointcut可以对相同的切入点进行一个抽取
@Before(value = "pointdemo()")
public void before(){
system.out .println(before...);
}
- 有多个增强类对同一个方法进行增强,可以设置增强类的优先级
- 在增强类上面添加注解@Order(数字类型值),数字类型值越小优先级越高
Aop操作(AspectJ配置文件)
- 创建两个类,增强类,和被增强类,创建方法
- 在spring配置文件中添加两个类的对象
(前两部过于简单,不在赘述) - 在spring配置文件中配置切入点
<!--配置aop增强-->
<aop:config>
<!--切入点-->
<aop:pointcut id ="p" expression = "execution([权限修饰符][返回类型][包全路径][方法名]([参数列表]) )">
<!--配置切面-->
<aop: aspect ref= "bookproxy">
<!--增强作用在具体的方法上-->
<aop: before method = "before" pointcut-ref="p">
</aop:aspect>
</aop:config>
jdbcTemplate(概念和准备)
什么是jdbcTemplate
- Spring框架对jdbc进行封装,使用JdbcTemplate方便实现对数据库操作
准备工作
- 导包
- 在spring配置文件中 配置连接池
- 配置jdbcTemplate对象,注入DataSource(在bean文件里)
<bean id="" class= "org.springframework.jdbc.core.jdbcTemplate" >
<!--注入datasource-->
<property name= "dataSource" ref = "dataSource"></property>
</bean>
- 创建service,创建dao类,在dao注入jdbcTemplate对象
//创建一个service包
@Service
public class BookService{
//注入dao
@Autowired
private UserDao userDao;
}
//创建一个dao包
public interface userDao{
}
@Repository
public class userDaoImp implements userDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
}
配置文件
<context:component-scan base-package="上层包路径"></context:component-scan>
jdbcTemplate操作数据库(添加)
- 对应数据库创建实体类
对应的表为:
public class User{
private String userId;
private String username;
private String ustatus;
public void setUserId(String userId){
this.userId = userId;
}}
public void setUsername(String username){
this.username= username;
}
public void setUstatus(String ustatus){
this.ustatus = ustatus;
}
public Sting getUserid(){
return userId;
}
public String getUsername(){
return username;
}
publci String getUstatus(){
return ustatus;
}
- 编写service和dao
- 在dao进行数据库添加操作
- 调用jdbcTemplate 对象里面的update方法实现添加操作
update (String sql,Object… args)【有两个参数–第一个参数是sql语句,第二个参数是:可变参数,指的是设置sql语句的值】
//创建一个service包
@Service
public class userService{
//注入dao
@Autowired
private UserDao userDao;
//添加的方法
public void adduser(User user){
userdao.add(user);
}
}
//创建一个dao包
public interface userDao{
void add(User user);
}
@Repository
public class userDaoImp implements userDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
//添加方法实现
@Override
public void add(User user){
Sting sql = "insert into t_user values(?,?,?)"
jdbcTemplate .updata(sql,user.getUserId,user.getUsername(),user.getUstatus() );
}
}
剩下的删,改,查功能类似(这里就不再赘述。。)
jdbcTemplate操作数据库(批量操作)
1.批量操作:操作表里面多条记录
2.jdbcTemplate实现批量添加操作
batchUpdate(String sql,List<Object[]> batchArgs)(有两个参数 第一个参数:sql语句,第二个参数:List集合,添加多条记录数据)
Spring中进行事务管理操作
一般来说,有两种方式可供使用:编程式事务管理,和声明式事务管理(推荐使用)
声明式事务管理
- 基于注解方式(推荐使用)
- 基于xml配置文件方式
在spring进行声明式事务管理,底层使用的是Aop原理
spring事务管理ApI
- 提供一个接口,表示事务管理器,这个接口针对不同的框架提供不同的实现类
事务操作(注解方式实现声明式事务管理)
- 在spring:配置文件配置事务管理器
<bean id ="transactionManager" class ="org.springframework.jdbc,datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name = "dataSource" ref="dataSource"></property>
</bean>
- 在spring配置文件中开启事务注解
- 在spring配置名称空间 tx
- 在配置文件中开启事务的注解
<tx:annotation-driven transaction-manager ="transactionManager"></tx:annotation-driven>
- 在service类上面(获取service类里面方法上面)添加事务注解
- @Transactional,这个注解可以添加到类上面,也可以添加到方法上面
- 如果把这个注解添加到类上面,这个类里面所有方法都添加事务
- 如果把这个注解添加方法上面,为这个方法添加事务。
事务操作(声明式事务管理参数配置)
- 在@Transactional里面,可以配置事务相关参数
- propagation :事务传播行为
1.多事务方法直接进行调用,这个过程中事务是如何进行管理的(事务方法:对数据库表数据进行变化的操作)
通俗解释:
- REQURED:如果add方法本身有事务,调用update方法之后,update使用当前add方法中的事务,如果add方法本身没有事务,调用update方法之后,创建新事务。
- REQURED_NEW:使用add方法调用update方法,add无论是否有事务,都会创建新的事务
- ioslation: 事务隔离级别
@Transaction(isolation = isolation.PEPEATABLE_READ)
- timeout:超时时间
- readOnly:是否只读
- rollbackFor:回滚
- noRollbackFor:不回滚
Spring5的一些新的功能
Spring5框架核心容器支持@Nullable注解
- @Nullable注解可以使用在方法上面,属性上面,参数上面,表示方法返回可以为空,属性值可以为空,参数值可以为空。
- 注解用在方法上面,表示方法的返回值可以为空
String getId();
- 注解使用在方法参数里面,方法参数可以为空
public <T> void registerBean(@Nullable String beanName)
- 注解使用在属性上面,属性值可以为空
@Nullable
private String bookName;
Spring新功能(Webflux)
- SpringWebflux介绍
- 是Spring5添加的新模块,用于web开发,与SpringMvc类似,使用了当前一种比较流行的响应式编程出现的框架。
- 使用传统web框架,比如springMVC,这些基于Servlet容器,webflux是一种异步飞阻塞的框架,一部非阻塞的框架在Servlet3.1后才支持。Spirngwebflux的核心是基于Reactor相关API实现的。
- 异步非阻塞解释:(异步和同步:(异步和同步是针对调用者,调用者发送请求,如果等着对方回应之后才去作其他事情就是同步,如果发送请求后不等着对方回应就去做其他事情就是异步。))(阻塞和非阻塞:是针对被调用者,被调用者收到一个请求后,做完请求任务之后才给出反馈就是阻塞,收到请求之后马上给出反馈后然后再去做事情就是非阻塞)
Webflux特点
第一 非阻塞式 :在有限资源下,提高系统吞吐量和伸缩性,以Reactor为基础来实现响应式编程
第二 函数式编程:spring5框架是基于java8,webflux使用java8函数式编程方式实现路由请求
比较springMVC