Spring框架笔记
IOC容器(控制反转)
什么是 IOC
<bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean>控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理。
使用IOC目的:
<bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean>降低耦合度
<bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean>通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象引用传递给他。也可以说依赖被注入到对象中。
IOC 底层原理
<bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean>工厂模式(解耦操作),反射(得到.class文件),xml解析
工厂解耦过程:

IOC 解耦过程
- xml配置文件,配置创建的对象
- [/code]
- [*]有service和dao类,创建工厂类
- [code]//创建工厂类
- class UserFactory{
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public static UserDao getDao(){
- <bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>//xml解析
- <bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>String classValue = class属性值;
- <bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>//通过反射创建对象
- <bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>Class class = Class.forName(classValue);
- <bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>return (UserDao)class.newInstance;
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}
- }
复制代码 IOC (接口)
- IOC思想基于 IOC 容器完成,IOC 容器底层就是对象工厂
- Spring提供了IOC容器实现两种方式:(两个接口)
(1)BeanFactory:IOC容器里面最基本的实现方式,是Spring内部的接口,不提供开发人员使用
特点:加载配置文件时,不会创建对象,在获取或者使用的时候才会创建对象
(2)ApplicationContext:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人员进行使用。
特点:加载配置文件的时候就会把配置文件对象进行创建
- ApplicationContext接口有实现类(ctrl + h查看接口)
IOC 操作 Bean 管理
- 什么是 Bean 管理
(1)Spring 创建对象
(2)Spring 注入属性
- Bean 管理操作有两种方式
(1)xml配置文件实现
(2)基于注解方式实现
基于xml方式
- 基于xml创建对象
- [/code](1)在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
- (2)在bean标签有很多属性,介绍常用的属性
- [list]
- [*]id 属性:唯一标识
- [*]class 属性:创建对象所在类的全路径(包类路径)
- [/list](3)创建对象时, [b]默认也是执行无参构造方法[/b]
- [*][size=2]基于xml方式注入属性[/size]
- (1)DI:依赖注入,就是注入属性。是IOC的一种具体实现方式。
- [list]
- [*]第一种注入方式:
- [b]使用set方法注入[/b]
- [code]public void setUserName(String name){
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>this.name = name;
- }
- //main方法中调用创建UserName并调用set方法
- UserName username = new UserName();
- username.setUserName("jack");
复制代码 在spring配置文件配置对象创建,配置注入属性(xml中的配置)- <bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>
复制代码 - 第二种注入方式:
有参构造注入- UserName userName = new UserName("jack");
复制代码 具体步骤:
(1)创建类,定义属性,创建属性对应有参构造方法。- // 1.加载spring配置文件
- ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml")
- // 2.获取配置创建的对象
- Orders orders = context.getBean("odders",Orders.class)
复制代码 (2)在spring配置文件(xml中的配置)配置对象创建,配置注入属性- <bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean>
复制代码 (2)注入空值特殊符号- // 注入空值
- <null/>
- //特殊符号 1.把<>进行转义 <> 2.把带特殊符号的内容写到CDATA中
- <property name="address"><value><![CDATA[<<南京>>]]></value></property>
复制代码 (3)注入属性-外部bean
- 创建两个类service类和dao类
- //在xml中service和dao对象创建
- <bean id="userService" >
- //注入userDao对象<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>name属性:类里面属性名称 ref属性:创建userDao对象bean标签id值
- // ref里面的名称要和id 的userDao一样
- <property name="userDao" ref="userDao"></property>
- </bean>
- <bean id="userDao" ></bean>
复制代码 - 在service调用dao里面的方法
- 在spring配置文件中进行配置
(4)注入属性-外部bean和级联赋值
xml注入集合属性
- 注入数组类型属性
- <bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean><bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean>java<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>mysql<bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean>
复制代码 - 注入List集合类型属性
- <bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean><bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean>lgm<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>lgm<bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean>
复制代码 - 注入Map集合类型属性
- <bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean><bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean><bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean><bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean>
复制代码 - 注入set集合类型属性
- <bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean><bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean>....<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean>....<bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean>
复制代码 - 在集合里面设置对象类型值
- 建立类
- public class Course{
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>.......
- }
复制代码 - 配置文件注入
- <bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean><bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean><bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean>
复制代码
- 把集合注入部分提取出来
FactoryBean
- Spring有两种类型 bean ,一种普通 bean ,另外一种是工厂 bean (FactoryBean)
- 普通 bean:在配置文件中定义 bean 类型就是返回类型
- 工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样
第一步 创建类,让这个类作为工厂 bean ,实现接口 FactoryBean
第二步 实现接口里面的方法,在实现方法中定义返回的 bean 类型
bean 的作用域
- 在 Spring 里面,可以设置创建的 bean 实例是单实例还是多实例
- 在 Spring 里面,默认情况下,创建的 bean 是单实例对象(可以通过设置成多实例)
- 如何设置单实例还是多实例
(1)在spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例
(2)scope属性值:
<bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean><bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean><bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean>第一个值,singleton,表示是单实例对象
<bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean><bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean><bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean>第二个值,prototype,表示是多实例对象- //配置bean.xml文件<bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean>
复制代码 - 演示添加后置处理器
- 创建类,实现接口 BeanPostProcessor,创建后置处理器 17集 21:00
- public class MyBeanPost implements BeanPostProcessor {
- }
复制代码
Xml的自动装配
- 什么是自动装配
- 根据指定装配规则(属性名称或者属性类型),spring自动将匹配的属性值进行注入
- 演示自动装配过程
外部属性文件
- 直接配置数据库的信息
- 配置德鲁伊连接池
- 引入德鲁伊连接池依赖jar包
- <bean id="dataSource" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="driverClassName" value=""></property>//数据库驱动
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="url" value="jdbc:mysql://locahost:3306/userDb"></property>//数据库地址
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="username" value="root"></property>//数据库用户名
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="password" value="root"></property>//数据库密码
- </bean>
复制代码
- 引入外部属性文件配置数据库连接池
- 创建外部属性文件,properties 格式文件,写入数据库信息
- prop.driverClass=com.mysql.jdbc.Driver
- prop.url=jdbc:mysql://locahost:3306/userDb
- prop.password=root
- prop.passName=root
复制代码 - 把外部properties属性文件引入到spring配置文件中
1.引入context名称空间- [/code]2.引入外部属性文件
- [code]//配置连接池 value值写表达式,不写定值<bean id="dataSource" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="driverClassName" value=""></property>//数据库驱动
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="url" value="jdbc:mysql://locahost:3306/userDb"></property>//数据库地址
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="username" value="root"></property>//数据库用户名
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="password" value="root"></property>//数据库密码
- </bean>
复制代码
基于注解方式
什么是注解
注解是代码里面的特殊标记。格式:@注解名称(属性名称=属性值,属性名称=属性值)
- 使用注解,注解在什么地方用。
类上面,方法上面,属性上面
- 使用注解目的:简化xml配置
Spring针对bean管理中创建对象提供注解
- @component
- @Service
- @Controller
- @Repository
四个注解功能是一样的,都可以用来创建bean实例
- 基于注解方式实现对象创建
<bean id="transactionManager2" >
<property name="dataSource" ref="dataSource"></property>
</bean>第一步 引入依赖 jar包
<bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean>第二步 开启组件扫描- //如果扫描多个包,中间可以用逗号隔开
- //扫描包上层目录(所以文件全部扫描)
- <context:component-scan base-package="com.atguigu.spring5.dao,com.atguigu.spring5.service"></context:component-scan>
复制代码 <bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean>第三步 创建类,在类上面添加创建对象注解- @component(value = "userService")public class UserService{<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public void add(){<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>System.out.println("service add ...");<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}}
复制代码 第四部 组件设置扫描那些文件 context.include-filter- //部分扫描 include-filter<bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean>//部分不扫描 exclude-filter<bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean>
复制代码 - 基于注解方式实现属性注入
- @AutoWired :根据属性类型进行自动装配
第一步 把 service 和 dao 对象创建,在service 和 dao 类添加创建对象的注解
第二步 在 service注入 dao 对象,在service 类添加 dao 类型属性,在属性上面使用注解
- @Qualifier :根据属性名称进行注入
@Qualifier注解的使用和@AutoWired一起使用
- @Resource :根据类型注入,可以根据名称注入
- import javax.annotation.Resource;
- @Resource (name = "userDaoImpl") //根据名称进行注入
- private UserDao userDao;
复制代码 - @Value :注入普通类型属性
- @value(value = "abc")
- private String name;
复制代码
完全注解开发
- import org.apringframework.context.annotation.Configuration;
- //创建配置类,替代xml配置文件
- @Configuration
- @componentScan(basePackages = {"com.atguigu"})
- public void Configuration{
- }
- //编写测试类
- public void testService(){
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>//加载配置类
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>UserService userService = context.getBean("userService",UserService.class);
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>userService.add();
- }
复制代码 Aop
什么是Aop
<bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean>面向切面编程,利用 AOP 可以对业务逻辑的各个部分进行隔离。从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发效率。
<bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean>通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
AOP底层原理
- AOP底层使用动态代理
1.有两种情况的动态代理
- 有接口情况,使用JDK动态代理
- 没有接口情况,使用CGLIB动态代理
创建子类的代理对象,增强类的方法
JDK动态代理
使用JDK动态代理,使用 Proxy 类里面的方法创建代理对象,调用 newProxyInstance 方法
方法里面有三个参数,
第一个参数:ClassLoader 类加载器
第二个参数:类[ ] interfaces 增强方法所在的类,这个类实现的接口,支持多个接口
第三个参数:InvocationHandler 实现这个接口,创建代理对象,写增强的方法- newProxyInstance(ClassLoader loader , 类<?>[ ] interfaces ,InvocationHandler h)
复制代码 创建接口,定义方法- package com.company.spring5;
- //UserDao接口
- public interface UserDao {
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public int add(int a, int b);
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public String upadte(String id);
- }
复制代码 创建接口实现类 UserDaoImpl,实现方法- package com.company.spring5;public class UserDaoImpl implements UserDao{<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>@Override<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public int add(int a, int b) {<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>return a + b;<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>@Override<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public String upadte(String id) {<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>return id;<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}}
复制代码 使用 Proxy- package com.company.spring5;import java.util.Arrays;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class JDKProxy {<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public static void main(String[] args) {<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>//创建接口实现类的代理对象<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>Class[] interfaces = {UserDao.class};//<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new InvocationHandler() {//<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean><bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>@Override//<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean><bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean><bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>return null;//<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean><bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}//<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>});<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>UserDaoImpl userDao = new UserDaoImpl();<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(),interfaces,new UserDaoProxy(userDao));<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>int result = dao.add(1,2);<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>System.out.println("result:"+ result);<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}}//创建代理对象代码class UserDaoProxy implements InvocationHandler{<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>//1.把创建的是谁的代理对象,把谁传递过来<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>//有参数的构造传递<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>private Object obj;<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public UserDaoProxy(Object obj){<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>this.obj = obj;<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>//增强逻辑<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>@Override<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>//方法之前<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>System.out.println("方法之前执行...."+ method.getName()+"传递的参数"+ Arrays.toString(args));<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>//被增强的方法执行<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>Object res = method.invoke(obj,args);<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>//方法之后<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>System.out.println("方法之后执行"+obj);<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>return res;<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}}
复制代码 AOP术语
- 连接点
类里面那些方法可以被增强,这些方法称为连接点
- 切入点
实际被真正增强的方法,成为切入点
- 通知(增强)
(1)实际增强的逻辑部分成为通知(增强)
(2)通知有多种类型
- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知 finally
- 切面
是动作
AOP操作(准备)
- Spring框架中一般基于AspectJ实现AOP操作
(1)什么是AspectJ
- AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和 Spring 框架一起使用,进行 AOP 操作
- 基于AspectJ 实现 AOP 操作
- 在项目工程里面引入 AOP 相关依赖<bean id="transactionManager2" >
<property name="dataSource" ref="dataSource"></property>
</bean>jar包
- 切入点表达式
- 切入点表达式作用:知道对哪个类型里面的哪个方法进行增强
- 语法结构:
- execution([权限修饰符][返回类型][类全路径][方法名称][参数列表])
- //举例1 对com.atguigu.dao.BookDao类里面的 add 进行增强
- excution(*com.atguigu.dao.BookDao.add(..))// *表示任意修饰符
- //举例2 对com.atguigu.dao.BookDao类里面的所有方法进行增强
- excution(*com.atguigu.dao.BookDao.*(..))
- //举例3 对com.atguigu.dao包里面所有类,类里面所有方法进行增强
- excution(*com.atguigu.dao.*.*(..))
复制代码
AspectJ注解
- 创建类,在类里面定义方法
- //被增强类public class User {<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public void add(){<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>System.out.println("add....");<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}}
复制代码 - 创建增强类(编写增强逻辑)
- //增强类public class UserProxy {<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>//前置通知<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public void before(){<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>System.out.println("before.....");<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}}
复制代码 - 进行通知的配置
(1)在spring配置文件中,开启注解扫描- [/code](2)使用注解创建 User 和 UserProxy 对象
- [code]import org.springframework.stereotype.Component;//被增强类@Componentpublic class User{<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public void add(){<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>System.out.println("add....");<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}}//增强类@Component@Aspect //第(3)步public class UserProxy {<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>//前置通知<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>//@Before注解表示作为前置通知<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>@Before(value="execution(*com.atguigu.spring5.aopanno.User.add(..))")<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public void before(){<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>System.out.println("before.....");<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}}
复制代码 (3)在增强类上面添加注解@Aspect
(4)在 spring 配置文件中开启生成代理对象- [/code]
- [*]配置不同类型的通知
- (1)在增强类的里面,在作为通知方法上面添加通知类型的注解,使用切入点表达式配置内容
- [/list][size=3]AspectJ配置文件[/size]
- [list=1]
- [*]创建两个类,增强类和被增强类,创建方法
- [*]在spring 配置文件中创建两个类对象
- [*]在 spring 配置文件中配置
- [/list][size=5]JdbcTemplate[/size]
- [size=4]什么是JdbcTemplate[/size]
- [list=1]
- [*]Spring框架对JDBC进行封装,使用 JdbcTemplate 方便实现对数据库操作
- [*][url=https://blog.csdn.net/qq_40643699/article/details/115582536]CSDN相关博客[/url]
- [/list][size=4]准备工作[/size]
- [list=1]
- [*]引入相关jar包
- [*][在Spring配置文件配置数据库连接池]
- [code]<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean><bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>
复制代码 - 配置 JdbcTemplate
- <bean id="UserName" >
- <constructor-arg name="UserName" value="jack"></constructor-arg>
- </bean><bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
复制代码 - 创建 service 类,创建dao 类,在 dao 注入 jdbcTemplate 对象
- //xml中配置
- <context:component-scan base-package="com.atguigu"></context:component-scan>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- //Java文件中
- @service
- public class BookService{
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>//注入dao
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>@Autowired
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>private BookDao bookDao;
- }
- // Dao
- @Repository
- public class BookDaoImpl implements BookDao{
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>//注入 JdbcTemplate
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>@Autowired
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>private JdbcTemplate jdbcTemplate;
- }
复制代码 JdbcTemplate操作数据库
增加,删除
- 创建类和实体方法
- package com.company.entity;public class User {<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>private String userId;<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>private String username;<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>private String ustatus;<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public String getUserId() {<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>return userId;<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public void setUserId(String userId) {<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>this.userId = userId;<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public String getUsername() {<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>return username;<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public void setUsername(String username) {<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>this.username = username;<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public String getUstatus() {<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>return ustatus;<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>public void setUstatus(String ustatus) {<bean id="UserName" >
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean><property name="UserName" value="jack"></property>
- </bean>this.ustatus = ustatus;<bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>}}
复制代码 - 编写 service 和 dao
(1)在 dao 进行数据库添加操作
(2)调用 JdbcTemplate 对象里面 update 方法实现添加操作
<bean id="transactionManager2" >
<property name="dataSource" ref="dataSource"></property>
</bean><bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean>有两个参数
<bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean><bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean>第一个参数: sql语句
<bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean><bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean>第二个参数: 可变参数,设置 SQL 语句值- //修改
- @Override
- public void updateBook(Book book){
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>String aql="update t_book set username=?,ustatus=? where user_id=?"
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>Object[] args = {book.getUsername(),book.getUstatus(),book.getUserId()};
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>int update = JdbcTemplate.update(sql,args);
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>System.out.println(update);
- }
复制代码 查询返回某个值
- 查询表里面有多少条记录,返回是某个值
- 使用 JdbcTemplate 实现查询返回某个值代码
有两个参数
第一个参数:SQL语句
第二个参数:返回类型Class
查询返回对象
- 场景:查询图书详情
- JdbcTemplate 实现查询返回对象
有三个参数
第一个参数:SQL语句
第二个参数:RowMapper 是接口,针对返回不同类型数据,使用这个接口里面实现类完成数据封装
第三个参数:SQL语句值
查询返回集合
- 场景:查询图书列表分页...
- 调用 JdbcTemplate 方法实现查询返回集合
批量添加操作
- 批量操作:操作表里面多条记录
- JdbcTemplate 实现批量添加操作
- batchUpdate(String sql,List<Object[]> batchArgs)
复制代码 两个参数
第一个参数:SQL语句
第二个参数:List 集合,添加多条记录数据
批量修改删除操作
事务管理
什么是事务
- 事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果一个失败所有操作都失败
- 最典型场景:银行转账
- 事务四个特性(ACID)
搭建事务操作环境

- 创建数据库表,添加记录
- 创建 service ,搭建 dao ,完成对象创建和注入关系
(1)service 注入 dao ,在 dao 注入JdbcTemplate ,在 JdbcTemplate注入 DataSource
- 在 dao 创建两个方法:多钱和少钱的方法,在service 创建方法(转账的方法)
Spring事务管理介绍
- 事务添加到JavaEE三层结构里面 Service 层(业务逻辑层)
- 在 Spring 进行事务管理操作
有两种方式:
编程式事务管理
声明式事务管理(一般使用声明式)
- 声明式事务管理
基于注解方式
基于 xml 配置文件方式
- 在 Spring 进行声明式事务管理,底层使用 AOP 原理
Spring事务管理API
- 提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类
接口<bean id="transactionManager2" >
<property name="dataSource" ref="dataSource"></property>
</bean>PlatformTransactionManager(org.springframework.transaction) 下的
DataDourceTransactionManger(org.springframework.jdbc.datasource)
注解声明式事务管理
- 在 Spring :配置文件中配置事务管理器
- <bean id="transactionManager2" >
- <property name="dataSource" ref="dataSource"></property>
- </bean>
复制代码 - 在 Spring 配置文件中,开启事务注解
- 在 Spring 配置文件中引入名称空间 tx
- 开启事务注解
- [/code]
- [/list]
- [*]在 service 类上面(获取 service 类里面方法上面)添加事务注解
- [list]
- [*]@Transactional , 这个注解添加到类上面,也可以添加到方法上面
- [*]如果把这个注解添加到类上面,这个类里面所有的方法都添加事务
- [*]如果把这个注解添加到方法上面,为这个方法添加事务
- [code]@Service
- @Transactional
- public class UserService{
- }
复制代码
事务参数
- propagation: 事务传播行为
当一个事务方法被另外一个事务方法调用时候,这个事务方法如何进行
- ioslation: 事务隔离级别
- 事务有特性成为隔离性,多事务操作之间不会产生影响。不考虑隔离性产生很多问题
- 有三个读问题:脏读、不可重复读、虚读
- 脏读:一个未提交的事务读取到了另一个未提交事务的数据。
- 不可重复读:一个未提交的数据读到了另外一个提交事务中的数据
- 虚读:一个未提交的事务读取到了另一个未提交事务添加的数据
- 解决:通过设置事务隔离性,解决上面问题
- repeatable MySQL默认隔离级别
- timeout : 超时时间
- 事务需要在一定时间内进行提交,如果不提交就会进行回滚
- 默认值是 -1(不超时)设置时间以秒为单位进行计算
- readOnly :是否只读
- 读:查询操作,写:添加修改删除操作
- readOnly 默认值为 false ,表示可以查询,可以添加修改删除操作
- 设置 readOnly 值为 true,设置为 true 之后,只能查询
- rollbackFor :回滚
- noRollbackFor :不回滚
XML声明式事务管理
- 在 Spring 配置文件中进行配置
第一步 配置事务管理器
第二步 配置通知
第三步 配置切入点和切面
Spring5 框架新功能
- <bean id="UserName" >
<constructor-arg name="UserName" value="jack"></constructor-arg>
</bean>整个Spring5基于java8,运行时兼容 JDK9,许多不建议使用的类型和方法在代码库中删除。
- Spring5框架自带了通用的日志封装
- Spring5已经移除Log4jConfigListener,官方建议使用Log4j2
- Spring5 框架整合 Log4j2
第一步:引入 jar 包
第二步:创建 Log4j2.xml配置文件
- Spring5 框架核心容器支持 @Nullable 注解
- @Nullable 注解可以使用在方法上面,属性上面,参数上面,表示方法返回可以为空,属性可以为空,参数值可以为空
- Spring5 核心容器支持函数式风格 GenericApplicationContext
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |