简介
Spring5框架
内容介绍:
1.Spring概念
2.IOC容器
3.Aop
4.JDBCTEmplate
5.事物管理
6.Spring5新特性
一.Spring框架概述
1.概述
(1)IOC:控制反转,将创建对象的过程交给Spring进行管理
(2)Aop:面向切面,功能增强不修改源代码
(1)解耦方便,开发简化
(2)Aop变成支持
(3)方便程序测试
(4)与其他框架集成方便
(5)方便事物操作
(6)降低API开发难度
2.入门案例
(1)下载spring
最后是这个网站
https://repo.spring.io/ui/native/release/org/springframework/spring/
下载解压
(2)创建新项目
(3)导入jar包
[外链图片转存失败,源站可能有防盗链机制,建议保存图片并直接上传(img-SWSNjI6C-1649754754216)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220314212314473.png)]
把所需的jar包导入其中
导入流程:
建立在项目文件夹中lab文件夹
把jar将包放入文件夹中
(4)创建普通类
在这一类中创建普通方法
(5)创建Spring配置文件
在配置文件中配置创建的对象
1.Spring使用配置文件xml文件格式
(6)编写测试代码
二.IOC容器
1.IOC底层原理
(1)什么是IOC
控制反转(Inversion of Control,缩写为IoC),它是面向对象编程的设计原则,可用于降低计算机代码之间的耦合。最常见的方法是依赖注入(Dependency Injection,简称DI),还有一种方法叫依赖搜索(Dependency Lookup)。通过控制逆转,当对象被创建时,调节系统中所有对象的外部实体将所依赖对象的引用传递给它。也可以说,依赖被注入对象。
(2)IOC底层原理
(1)xml分析、工厂模式、反射
(3)画图讲解IOC底层原理
[外链图片转存失败,源站可能有防盗链机制,建议保存图片并直接上传(img-SDr4j6ah-1649754754217)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220316111726329.png)]
(1)配置xml文件配置创建的对象
(2)有service类和dao创建工厂类
2.IOC接口(BeanFactory)
)
IOC容器中最基本的实现方法Spring不提供开发人员使用内部接口
**特点:**加载配置文件时不会创建对象,只有在获取对象(使用)时才会创建对象
BeanFactory接口的子接口提供越来越强大的功能,通常由开发人员使用
**特点:**在加载配置文件时,将创建配置文件的对象
FlieSystemXmlApplicationContext对应电脑的盘符路径
ClassPathXmlApplicationContext类路径
3.IOC操作Bean管理(基于xml)
(1)Bean管理定义:
Bean管理是指两个操作
1.Spring创建对象
2.Spring注入属性
(2)Bean两种管理操作方式
1.基于xml创建对象的方法 2.基于注释方法的实现
1.基于xml实现文件配置模式
<!--配置User对象创建--> <bean id = "user" class="com.spring.User"></bean>
(1)在Spring中使用bean在标签中添加相应的属性可以创建对象
(2)在bean标签中有许多属性,介绍常用属性
*id属性:唯一的标识
*class属性:类全路径(包类路径)
*name属性:和id一样,但是在name可以添加一些特殊符号
(3)创建对象时,默认执行无参数结构方法
2.基于xml注入属性的方式
(1)DI:依赖注入是注入属性
3.第一种注射方式:使用set注入方法
(1)创建类,定义属性和对应的set方法
(2)在Spring创建配置文件配置对象,注入配置属性
最后测试:
4.第二种注入方式:通过参考结构注入
(1)创建类,定义属性,创建属性对应参数结构方法
(2)在Spring配置在文件中
测试:
5.p注入名称空间(理解)
(1)注入P名空间可以简化xml配置方式
第一步:在配置文件中添加p名空间
第二步:注入属性,在bean操作标签
测试:
(3)IOC操作Bean管理(xml注入其他类型的操作)
one:null值
eg:
测试:
two:属性值包含特殊符号
1.把<>进行转义<>
2.把带特殊符号内容写到CDATA
测试:(两个的输出结果都一样)
three:注入属性-外部bean
1.创建两个类service和dao类
2.在service调用dao里面的方法
3.在Spring配置文件中进行配置
测试:
four:注入属性-内部bean
-
一对多关系:部门和员工
一个部门有多个员工,一个员工属于一个部门
部门是一,员工是多
-
在实体类之间表示一对多的关系,员工表示所属部门,使用对象类型属性进行表示
-
在Spring的配置文件中进行配置
测试:
five:注入属性-级联赋值
测试:
Dept.java
Testbean.java同上
测试:
(4)IOC操作Bean管理(xml注入集合属性)
-
注入数组类型属性
-
注入List集合类型属性
-
注入Map集合类型属性
1.创建类
package com.spring.collectiontype;
import java.nio.MappedByteBuffer;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author yanchaochao
* @date 2022/3/17 20:34
*/
public class Stu {
//1.数组类型
private String[] courses;
//2.list集合类型属性
private List<String> list;
//3.创建Map集合属性
private Map<String,String> maps;
//4.set集合类型
private Set<String> 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;
}
public void setSets(Set<String> sets) {
this.sets = sets;
}
//测试
public void test(){
System.out.println(Arrays.toString(courses));
System.out.println(list);
System.out.println(maps);
System.out.println(sets);
}
}
<?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">
<!--1.集合类型属性注入-->
<bean id="stu" class="com.spring.collectiontype.Stu">
<!--数组类型属性注入-->
<property name="courses">
<array>
<value>java</value>
<value>c</value>
<value>c++</value>
<value>算法</value>
<value>mysql</value>
</array>
</property>
<!--list类型属性注入-->
<property name="list">
<list>
<value>张三</value>
<value>小三</value>
</list>
</property>
<!--map类型属性注入-->
<property name="maps">
<map>
<entry key="JAVA" value="java"></entry>
<entry key="C" value="c"></entry>
</map>
</property>
<!--set类型属性注入-->
<property name="sets">
<set>
<value>MySQL</value>
<value>Redis</value>
</set>
</property>
</bean>
</beans>
测试:
package com.spring.testdemo;
import com.spring.collectiontype.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author yanchaochao
* @date 2022/3/17 21:19
*/
public class Testcollectiontype {
@Test
public void testCollection(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
Stu stu = context.getBean("stu", Stu.class);
stu.test();
}
}
<!--创建多个course对象-->
<bean id="course1" class="com.spring.collectiontype.Course">
<property name="cname" value="Spring5框架"></property>
</bean>
<bean id="course2" class="com.spring.collectiontype.Course">
<property name="cname" value="MySQL数据库"></property>
</bean>
<!--注入list集合类型,值是对象-->
<property name="courseList">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
Course.java
package com.spring.collectiontype;
/**
* @author yanchaochao
* @date 2022/3/17 21:40
*/
public class Course {
private String cname;//课程名称
public void setCname(String cname) {
this.cname = cname;
}
@Override
public String toString() {
return "Course{" +
"cname='" + cname + ''' +
'}';
}
}
Stu.java
package com.spring.collectiontype;
import java.nio.MappedByteBuffer;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author yanchaochao
* @date 2022/3/17 20:34
*/
public class Stu {
//1.数组类型
private String[] courses;
//2.list集合类型属性
private List<String> list;
//3.创建Map集合属性
private Map<String,String> maps;
//4.set集合类型
private Set<String> sets;
//学生所学多门课程
private List<Course>courseList;
public void setCourseList(List<Course> courseList) {
this.courseList = courseList;
}
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;
}
public void setSets(Set<String> sets) {
this.sets = sets;
}
//测试
public void test(){
System.out.println(Arrays.toString(courses));
System.out.println(list);
System.out.println(maps);
System.out.println(sets);
System.out.println(courseList);
}
}
bean1.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" xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd">
<!--1.集合类型属性注入-->
<bean id="stu" class="com.spring.collectiontype.Stu">
<!--数组类型属性注入-->
<property name="courses">
<array>
<value>java</value>
<value>c</value>
<value>c++</value>
<value>算法</value>
<value>mysql</value>
</array>
</property>
<!--list类型属性注入-->
<property name="list">
<list>
<value>张三</value>
<value>小三</value>
</list>
</property>
<!--map类型属性注入-->
<property name="maps">
<map>
<entry key="JAVA" value="java"></entry>
<entry key="C" value="c"></entry>
</map>
</property>
<!--set类型属性注入-->
<property name="sets">
<set>
<value>MySQL</value>
<value>Redis</value>
</set>
</property>
<!--注入list集合类型,值是对象-->
<property name="courseList">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
</bean>
<!--创建多个course对象-->
<bean id="course1" class="com.spring.collectiontype.Course">
<property name="cname" value="Spring5框架"></property>
</bean>
<bean id="course2" class="com.spring.collectiontype.Course">
<property name="cname" value="MySQL数据库"></property>
</bean>
</beans>
Testcollectiontype.java
package com.spring.testdemo;
import com.spring.collectiontype.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author yanchaochao
* @date 2022/3/17 21:19
*/
public class Testcollectiontype {
@Test
public void testCollection(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
Stu stu = context.getBean("stu", Stu.class);
stu.test();
}
}
测试:
(1)在spring配置文件中引入名称空间util
(2)使用util标签完成list集合注入提取
Book.java
package com.spring.collectiontype;
import java.util.List;
/**
* @author yanchaochao
* @date 2022/3/17 21:55
*/
public class Book {
private List<String>list;
public void setList(List<String> list) {
this.list = list;
}
public void test(){
System.out.println(list);
}
}
bean2.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"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!--1.提取list集合类型注入-->
<util:list id="booklist">
<value>JAVA</value>
<value>C</value>
<value>MySQL</value>
<value>C++</value>
<value>Git</value>
</util:list>
<!--2.提取list集合类型属性注入使用-->
<bean id="book" class="com.spring.collectiontype.Book">
<property name="list" ref="booklist"></property>
</bean>
</beans>
测试:
package com.spring.testdemo;
import com.spring.collectiontype.Book;
import com.spring.collectiontype.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author yanchaochao
* @date 2022/3/17 22:03
*/
public class TestBook {
@Test
public void testBook(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
Book book = context.getBean("book", Book.class);
book.test();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JH1BJ9hR-1649754754228)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220317221208513.png)]
(5)IOC操作Bean管理(FactoryBean)
-
Spring有两种类型Bean,一种普通bean,另外一种工厂bean(FactoryBean)
-
普通Bean:在配置文件中定义Bean类型就是返回类型
-
工厂Bean:在配置文件定义Bean类型可以和返回类型不一样
第一步:创建类,让这个类作为工厂bean,实现接口FactoryBean
第二步:实现接口里面的方法,在实现的方法中定义返回的bean类型
MyBean.java
package com.spring.factorybean;
import com.spring.collectiontype.Course; import org.springframework.beans.factory.FactoryBean;
/**
-
@author yanchaochao
-
@date 2022/3/17 22:21 */ public class MyBean implements FactoryBean {
//定义类型和返回类型不一样 //定义返回bean @Override public Course getObject() throws Exception { Course course = new Course(); course.setCname(“abc”); return course; }
@Override public Class<?> getObjectType() { return null; }
@Override public boolean isSingleton() { return FactoryBean.super.isSingleton(); } }
bean3.xml
<?xml version="1.0" encoding="UTF-8"?><bean id="myBean" class="com.spring.factorybean.MyBean"> </bean>
-
测试:
package com.spring.testdemo;
import com.spring.collectiontype.Course;
import com.spring.collectiontype.Stu;
import com.spring.factorybean.MyBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author yanchaochao
* @date 2022/3/17 22:23
*/
public class Testfactorybean {
@Test
public void testFactoryBean(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
Course course = context.getBean("myBean", Course.class);
System.out.println(course);
}
}
(6)IOC操作Bean管理(Bean的作用域)
由图可得出,输出的两个地址是一样的,所以可以得出在默认情况下bean是单实例对象
(1)在Spring配置文件bean标签里面有属性用于设置单实例还是多实例
(2)scope属性值
第一个值 默认值,singleton,表示单实例对象
第二个值 prototype,表示多实例对象
测试:
两个对象的地址不一样
(3)singleton和prototype区别
-
singleton表示单实例,prototype表示多实例
-
设置scope值是时候,加载spring的时候就会创建单实例对象
设置scope值是时候,不是在加载spring配置文件时候创建对象,在调用getBean方法创建多实例对象
(7)IOC操作Bean管理(生命周期)
1.生命周期
从对象到对象销毁的过程
2.bean生命周期
(1)通过构造器创建bean实例(无参数构造)
(2)为bean的属性设置值和对其他bean的引用(调用set方法)
(3)调用bean的初始化的方法(需要进行配置)
(4)bean可以直接使用了(对象获取到了)
(5)当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁)
3.演示bean的生命周期
Order.java
package com.spring.bean;
/**
* @author yanchaochao
* @date 2022/3/18 19:48
*/
public class Order {
private String oname;
//无参数构造
public Order(){
System.out.println("第一步,执行无参构造实例");
}
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步,调用set方法调用初始化值");
}
//创建执行初始化的方法
public void initMethod(){
System.out.println("第三部,执行初始化方法");
}
//执行销毁的方法
public void destroyMethod(){
System.out.println("第五步执行销毁的方法");
}
}
bean4.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"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="orders" class="com.spring.bean.Order" init-method="initMethod" destroy-method="destroyMethod">
<property name="oname" value="手机"></property>
</bean>
</beans>
测试:
Testbean.java
package com.spring.testdemo;
import com.spring.bean.Order;
import com.spring.collectiontype.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author yanchaochao
* @date 2022/3/18 19:54
*/
public class Testbean {
@Test
public void testBook(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
Order order = context.getBean("orders", Order.class);
System.out.println("第四步,得到对象");
System.out.println(order);
//手动销毁
context.close();
}
}
4.bean的后置处理
(1)通过构造器创建bean实例(无参数构造)
(2)为bean的属性设置值和对其他bean的引用(调用set方法)
(3)把bean实例传递bean后置处理器的方法
postProcessBeforeInitialization
(4)调用bean的初始化的方法(需要进行配置)
(5)把bean实例传递bean后置处理器的方法
postProcessAfterInitialization
(6)bean可以直接使用了(对象获取到了)
(7)当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁)
5.演示添加后置处理器效果
(1)创建类,实现接口BeanPostProcessor,创建后置处理器
MyBeanPost.java
package com.spring.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.Nullable;
/**
* @author yanchaochao
* @date 2022/3/18 20:17
*/
public class MyBeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之前执行的方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之后执行的方法");
return bean;
}
}
Order.java
package com.spring.bean;
/**
* @author yanchaochao
* @date 2022/3/18 19:48
*/
public class Order {
private String oname;
//无参数构造
public Order(){
System.out.println("第一步,执行无参构造实例");
}
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步,调用set方法调用初始化值");
}
//创建执行初始化的方法
public void initMethod(){
System.out.println("第三部,执行初始化方法");
}
//执行销毁的方法
public void destroyMethod(){
System.out.println("第五步执行销毁的方法");
}
}
bean4.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"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="orders" class="com.spring.bean.Order" init-method="initMethod" destroy-method="destroyMethod">
<property name="oname" value="手机"></property>
</bean>
<!--配置后置处理器-->
<bean id="myBeanPost" class="com.spring.bean.MyBeanPost"></bean>
</beans>
Testbean.java
package com.spring.testdemo;
import com.spring.bean.Order;
import com.spring.collectiontype.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author yanchaochao
* @date 2022/3/18 19:54
*/
public class Testbean {
@Test
public void testBook(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
Order order = context.getBean("orders", Order.class);
System.out.println("第四步,得到对象");
System.out.println(order);
//手动销毁
context.close();
}
}
(8)IOC操作Bean管理(xml自动装配)
1.什么是自动装配
(1)根据指定装配规则(属性名称或者属性类型),spring自动将匹配的属性值进行注入
2.演示自动装配
(1)根据属性名称自动注入
<!--实现自动装配
bean标签属性autowire,配置自动装配
autowire属性常用两个值:
byName根据属性名称注入,注入值bean的id值和类属性名称一样
byType根据属性类型注入
-->
<bean id="emp" class="com.spring.autowire.Emp" autowire="byName">
根据属性名称注入,注入值bean的id值和类属性名称一样
(2)根据属性类型自动注入
<!--实现自动装配
bean标签属性autowire,配置自动装配
autowire属性常用两个值:
byName根据属性名称注入,注入值bean的id值和类属性名称一样
byType根据属性类型注入
-->
<bean id="emp" class="com.spring.autowire.Emp" autowire="byType">
(9)IOC操作Bean管理(外部属性文件)
1.直接配置数据库信息
(1)配置德鲁伊连接池
<!--直接配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/userDb" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
2.引入外部属性文件配置数据库连接池
(1)创建外部属性文件,properties格式文件,写数据库信息
(2)把外部properties属性文件引入到配置文件
*引入context名称空间
<?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:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
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/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
(3)在spring配置文件中使用标签引入外部属性文件
<!--引入外部属性文件-->
<context:property-placeholder location="classpath*:jdbc.properties"></context:property-placeholder>
<!--配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="driverClassName" value="${prop.driverClass}" />
<property name="url" value="${prop.url}" />
<property name="username" value="${prop.username}" />
<property name="password" value="${prop.password}" />
</bean>
4.IOC操作Bean管理(基于注解)
1.什么是注解
(1)注解是代码特殊标记,格式:@注解名称**()**
(2)使用注解,注解作用在类上面,方法上面,属性上面
(3)使用注解目的:简化xml配置
2.Spring针对Bean管理中创建对象提供注解
(1)@Component
(2)@Service
(3)@Controller
(4)@Repository
*上面四个注解功能是一样的,都可以用来创建bean实例
3.基于注解方式实现对象创建
(1)引入依赖
(2)开启组件扫描
(3)创建类,在类上面添加创建对象注解
package com.atguigu.spring5.testdemo;
import com.atguigu.spring5.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author yanchaochao
* @date 2022/3/22 14:31
*/
public class TestSpring5Demo1 {
@Test
public void testService(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService);
userService.add();
}
}
实例一:
实例二:
4.基于注解方式实现属性注入
第一步:把service和dao对象创建,在service和dao类添加创建对象注解
第二步:在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.java
package com.atguigu.spring5.dao;
public interface UserDao {
public void add();
}
UserDaoImpl
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao{
@Override
public void add(){
System.out.println("dao add...");
}
}
UserService.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@Service
public class UserService {
//定义dao类型的属性
//不需要添加set方法
//添加注入属性注解
@Autowired
private UserDao userDao;
public void add(){
System.out.println("service add.....");
userDao.add();
}
}
测试:
TestSpring5Demo1.java
package com.atguigu.spring5.testdemo;
import com.atguigu.spring5.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring5Demo1 {
@Test
public void testService(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService);
userService.add();
}
}
这个@Qualifier注解的使用,和上面@Autowired一起使用
5.完全注解开发
(1)创建配置类,替代xml的配置文件
package com.atguigu.spring5.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration //作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"com.atguigu"})
public class SpringConfig {
}
(2)编写测试类
@Test
public void testService2(){
//加载配置类
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService);
userService.add();
}
三.AOP
1.简介
AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
日志记录,性能统计,安全控制,事务处理,异常处理等等。
将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
eg:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CZDxwnkh-1649754754232)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220322201401950.png)]
2.底层原理
(1)有两种情况
:有接口的情况,使用JDK代理
创建接口实现代理对象,增强类的方法
:没有接口的情况,使用CGLIB代理
创建子类的代理对象,增强类的方法
3.AOP(JDK动态代理)
方法里有三个参数:
one:类加载器
two:增强方法所在的类,这个类实现的接口,支持多个接口
three:实现这个接口InvocationHandler,创建代理对象,写增强的方法
(1)创建接口,定义方法
package com.study;
public interface UserDao {
public int add(int a,int b);
public String update(String id);
}
(2)创建接口实现类,实现方法
package com.study;
public class UserDaoImpl implements UserDao{
@Override
public int add(int a, int b) {
System.out.println("add方法执行了......");
return a+b;
}
@Override
public String update(String id) {
System.out.println("update方法执行了......");
return id;
}
}
(3)使用Proxy类创建接口代理对象
package com.study;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
/**
* @author yanchaochao
* @date 2022/3/22 20:39
*/
public class JDKProxy {
public static void main(String[] args) {
//创建接口实现类代理对象
Class [] interfaces = {UserDao.class};
UserDaoImpl userDao = new UserDaoImpl();
UserDao dao =(UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
int result = dao.add(1,2);
System.out.println("result:"+result);
}
}
//创建代理对象代码
class UserDaoProxy implements InvocationHandler{
//1.把创建的是谁的代理对象,把谁传递过来
//有参数构造传递
private Object object;
public UserDaoProxy(Object object){
this.object = object;
}
//增强的逻辑
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法之前
System.out.println("方法之前执行......"+method.getName()+":传递参数..."+ Arrays.toString(args));
//被增强的方法
Object res = method.invoke(object, args);
//方法之后
System.out.println("方法执行之后......"+object);
return res;
}
}
结果:
4.AOP(术语)
一,连接点
二,切入点
三,通知(增强)
四,切面
5.AOP操作(准备)
(1)什么是AspectJ
*AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作
(1)基于xml配置文件实现
(2)jiyu注解方式实现
(1)切入点表达式作用:知道对哪个类型里面的哪个方法进行增强
(2)语法结构:
execution([][][][][][][][][权限修饰符] [返回类型] [类全路径] [方法名称] [参数列表])
举例1:对com.atguigu.dao.BookDao类里面的add进行增强
execution(*com.atguigu.dao.BookDao.add(…方法中的参数))
举例2:对com.atguigu.dao.BookDao类里面的所有方法进行增强
execution(*com.atguigu.dao.BookDao. * (…方法中的参数))
举例3:对com.atguigu.dao包里面的所有类,类里面的所有方法进行增强
execution(*com.atguigu.dao. *. * (…方法中的参数))
6.AOP操作(AspectJ注解)
1.创建类,在类里面定义方法
2.创建增强类(编写增强逻辑)
(1)在增强类里面,创建方法,让不同方法代表不同通知类型
package com.study.aopanno;
import org.springframework.stereotype.Component;
//被增强的类
@Component
public class User {
public void add (){
System.out.println("add...");
}
}
package com.study.aopanno;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
//增强的类
@Component
@Aspect //生成代理对象
public class UserProxy {
//前置通知
public void before(){
System.out.println("before......");
}
}
3.进行通知的配置
(1)在spring配置文件中,开启注解扫描
bean1.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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">
<!--开启注解扫描-->
<context:component-scan base-package="com.study.aopanno"></context:component-scan>
</beans>
(2)使用注解创建User和UserProxy对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1btLVhd8-1649754754235)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220323175417167.png)]
(3)在增强类上面添加注解@Aspect
(4)在spring配置文件中开启代理生成对象
<!--开启Aspect生成的代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
4.配置不用类型的通知
(1)在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
package com.study.aopanno;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* @author yanchaochao
* @date 2022/3/23 17:34
*/
//增强的类
@Component
@Aspect //生成代理对象
public class UserProxy {
//前置通知
//Before注解表示为前置通知
@Before(value = "execution(* com.study.aopanno.User.add(..))")
public void before(){
System.out.println("before......");
}
//最终通知
@After(value = "execution(* com.study.aopanno.User.add(..))")
public void after(){
System.out.println("after......");
}
//后置通知(返回通知)
@AfterReturning(value = "execution(* com.study.aopanno.User.add(..))")
public void afterReturning(){
System.out.println("afterReturning......");
}
//异常通知
@AfterThrowing(value = "execution(* com.study.aopanno.User.add(..))")
public void afterThrowing(){
System.out.println("afterThrowing......");
}
//环绕通知
@Around(value = "execution(* com.study.aopanno.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
System.out.println("环绕之前......");
//被增强的方法
proceedingJoinPoint.proceed();
System.out.println("环绕之后......");
}
}
TestAop.java
package com.study.test;
import com.study.aopanno.User;
import jdk.jfr.StackTrace;
import org.springframework.context.ApplicationContext;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAop {
@Test
public void testAopAnno(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
User user = context.getBean("user", User.class);
user.add();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xnZT7SSR-1649754754236)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220323225111843.png)]
5.公共切入点抽取
package com.study.aopanno;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
//增强的类
@Component
@Aspect //生成代理对象
public class UserProxy {
//相同切入点抽取
@Pointcut(value = "execution(* com.study.aopanno.User.add(..))")
public void piontdemo(){
}
//前置通知
//Before注解表示为前置通知
@Before(value = "piontdemo()")
public void before(){
System.out.println("before......");
}
//最终通知
@After(value = "execution(* com.study.aopanno.User.add(..))")
public void after(){
System.out.println("after......");
}
//后置通知(返回通知)
@AfterReturning(value = "execution(* com.study.aopanno.User.add(..))")
public void afterReturning(){
System.out.println("afterReturning......");
}
//异常通知
@AfterThrowing(value = "execution(* com.study.aopanno.User.add(..))")
public void afterThrowing(){
System.out.println("afterThrowing......");
}
//环绕通知
@Around(value = "execution(* com.study.aopanno.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
System.out.println("环绕之前......");
//被增强的方法
proceedingJoinPoint.proceed();
System.out.println("环绕之后......");
}
}
6.有多个增强类多同一个方法进行增强,设置增强类优先级
(1)在增强类上面添加注解@Order(数字类类值),数字类值越小优先级越高
PersonPerxy.java
package com.study.aopanno;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Order(1)
public class PersonPerxy {
//后置通知(返回通知)
@Before(value = "execution(* com.study.aopanno.User.add(..))")
public void afterReturning(){
System.out.println("Person Before......");
}
}
User.java
package com.study.aopanno;
import org.springframework.stereotype.Component;
//被增强的类
@Component
public class User {
public void add (){
System.out.println("add...");
}
}
UserProxy.java
package com.study.aopanno;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
//增强的类
@Component
@Aspect //生成代理对象
@Order(3)
public class UserProxy {
//相同切入点抽取
@Pointcut(value = "execution(* com.study.aopanno.User.add(..))")
public void piontdemo(){
}
//前置通知
//Before注解表示为前置通知
@Before(value = "piontdemo()")
public void before(){
System.out.println("before......");
}
//最终通知
@After(value = "execution(* com.study.aopanno.User.add(..))")
public void after(){
System.out.println("after......");
}
//后置通知(返回通知)
@AfterReturning(value = "execution(* com.study.aopanno.User.add(..))")
public void afterReturning(){
System.out.println("afterReturning......");
}
//异常通知
@AfterThrowing(value = "execution(* com.study.aopanno.User.add(..))")
public void afterThrowing(){
System.out.println("afterThrowing......");
}
//环绕通知
@Around(value = "execution(* com.study.aopanno.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
System.out.println("环绕之前......");
//被增强的方法
proceedingJoinPoint.proceed();
System.out.println("环绕之后......");
}
}
测试:
package com.study.test;
import com.study.aopanno.User;
import jdk.jfr.StackTrace;
import org.springframework.context.ApplicationContext;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAop {
@Test
public void testAopAnno(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
User user = context.getBean("user", User.class);
user.add();
}
}
7.AOP操作(AspectJ配置文件)
(1)创建两个类,增强类和被增强类,创建方法
package com.study.aopxml;
public class Book {
public void buy(){
System.out.println("buy.......");
}
}
package com.study.aopxml;
public class BookProxy {
public void Before(){
System.out.println("before.......");
}
}
(2)在spring配置文件中创建两个类对象
(3)在spring配置文件中配置切入点
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
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="book" class="com.study.aopxml.Book"></bean>
<bean id="bookProxy" class="com.study.aopxml.BookProxy"></bean>
<!--配置AOP增强-->
<aop:config>
<!--切入点-->
<aop:pointcut id="p" expression="execution(* com.study.aopxml.Book.buy(..))"/>
<!--配置切面-->
<aop:aspect ref="bookProxy">
<!--增强作用在具体的方法上-->
<aop:before method="Before" pointcut-ref="p"></aop:before>
</aop:aspect>
</aop:config>
</beans>
测试:
@Test
public void testBook(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
Book book = context.getBean("book", Book.class);
book.buy();
}
完全使用注解开发
不需要创建xml文件
package com.study.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan(basePackages = {"com.study"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}
四.JdbcTemplate
1.概念和准备
1.什么是JdbcTemplate
Spring框架对JDBC进行封装,使用JdbcTemplate方便对实现数据库操作
2.准备工作
(1)引入相关的jar包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iHCSmQ2K-1649754754237)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220328152239741.png)]
(2)在Spring配置文件中配置数据库的连接池
<!--配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="driverClassName" value="${prop.driverClass}" />
<property name="url" value="${prop.url}" />
<property name="username" value="${prop.username}" />
<property name="password" value="${prop.password}" />
</bean>
(3)JdbcTemplate对象,注入DataSource
<!--JdbcTemplate对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入dataSource数据源信息-->
<property name="dataSource" ref="dataSource"></property>
</bean>
(4)创建service类,创建dao类,在dao注入jdbcTemplate对象
配置文件中开启组件扫描
<!--组件扫描-->
<context:component-scan base-package="com.study"></context:component-scan>
service
@Service
public class BookService {
//注入dao
@Autowired
private BookDao bookDao;
}
dao
@Repository
public interface BookDao {
}
public class BookDaoImpl implements BookDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
}
2.JdbcTemplate操作数据库
(1)添加
1.对应数据库创建实体类
2.编写service和dao
(1)在dao进行数据库添加操作
(2)调用jdbcTemplate对象里面的update方法实现
*有两个参数
*第一个参数:sql语句
*第二个参数:可变参数,设置sql语句值
public class BookDaoImpl implements BookDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void add(Book book) {
//1.创建sql语句
String sql = "insert into t_book values(?,?,?)";
//2.调用方法实现
Object [] args = {book.getUserId(),book.getUsername(),book.getUstatus()};
int update = jdbcTemplate.update(sql,args);
//用法不一
// int update = jdbcTemplate.update(sql,book.getUserId(),book.getUsername(),book.getUstatus());
System.out.println(update);
}
}
测试类Test:
package com.study.test;
import com.study.entity.Book;
import com.study.service.BookService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author yanchaochao
* @date 2022/4/10 10:58
*/
public class TestBook {
@Test
public void testJdbcTemplate(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService", BookService.class);
Book book = new Book();
book.setUserId("1");
book.setUsername("ja