Spring5
课程内容
- spring概念
- IOC容器
- Aop
- JDBCTemplate(更方便和数据库操作)
- 事务的管理
Day1
框架概述EE
-
Spring是一个轻量级的开源的javaEE框架(开发更方便,更简洁)
-
Spring有很多组成部分,核心部分->IOC,AOP
(1)IOC:控制反转,创建对象的过程交给Spring管理,进行对象的实例化
(2)AOP:面向切面,不修改源代码增强我们的功能
-
Spring的特点: 方便解耦,简化开发,Aop编程支持,方便程序测试,方便和其他框架进行整合,降低javaApi的操作难度,方便进行事务的操作
入门案例
@Test
public void tess_bean1(){
//加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean1.xml");
//获取配置创建的对象
user user = applicationContext.getBean("user", user.class);
user.add();
}
}
<bean id="user" class="user"></bean>
//bean的属性
//id = 变量名
//class = new 的对象
//property 相当于给属性赋值
//ref: 引用Spring容器中创建好的对象
//value 具体的值, 基本数据类型!
IOC容器
IOC底层原理
-
什么是IOC: 控制反转(inversion of control)依赖被注入到对象中 ,将对象的创建和对象之间的调用过程都交给Spring管理
-
目的:为了耦合度降低
-
底层的原理: xml解析,工厂模式,反射(通过得到类的字节码文件)
-
IOC:过程,进一步降低耦合度
1.xml配置文件,配置创建的对象-->只需要修改配置文件 2.创建工厂类,xml解析获取class属性值(类信息),通过反射创建对象class.foName(),newInstance创建对象.
IOC接口
- IOC的思想基于IOC的容器,本质上就是对象的工厂
- Spring提供了IOC容器实现的两种方式,两个接口,BeanFactory(只会加载配置文件,只有当获取或使用对象的时候才会创建对象),ApplicationContext(加载配置文件的时候,就会将配置文件中的对象创建)
- BeanFactory:内置的最基本的方式,是spring内部使用的接口,开发一般不使用这个
- ApplicationContext:beanFactory的子接口,实现更强大的功能
ApplicationContext接口中有很多的实现类:
IOC容器:Bean管理XML方式(创建对象和set注入属性)
-
什么是bean管理:有两个操作
(1)spring创建对象 (2)spring注入属性(构造方法和set方法) -
管理操作的两种方式:
(1)Xml配置文件
1.基于xml创建对象 <bean id="user" class="user"></bean> id:给对象起一个标识,通过标识获取对象 class:创建对象所在类的全路径 name:与id作用是一样的,区别:name中可以有特殊符号 ref: 默认执行无参数的构造方法。 2. 基于xml注入属性: (1)DI,依赖注入就是注入属性(Di是IOC的一种实现) (2)有参构造注入: <bean id="book" class="Book"> <constructor-arg name="bnaeme" value="算法茹姐"></constructor-arg> <constructor-arg name="bAthuro" value="lcc"></constructor-arg> </bean> index="0",也是可以替代名称的 (3)set方法注入: <bean id="book" class="Book"> <property name="bnaeme" value="算法图解"/> <property name="bAthuro" value="lcc"/> </bean>p名称空间注入:简化基于xml配置的方式 添加p名称空间
进行属性注入--->还是一个set方法注入
xml注入其他属性:
- 字面量 设置一个空值 包含特殊符号 (1)转义(2)写入CDATA 《nanjin》
外部bean
- 创建两个类,service,dao,service调用dao的方法
可以通过创建属性,再使用set方法进行注入 - 注入属性,内部bean和级联赋值
部门(使用list存储员工)和员工(使用对象表示部门)是一对多的关系
ref, bean中嵌套一个bean - 注入数组属性
细节问题,如果放进去的为对象
公共的集合,util - 自动装配:不需要写property标签,(根据属性名称->autowire.ByName或者属性类型ByType进行自动装配)
bean的id的值和类属性名称要一样
类型:会有类型对应多个的时候会有问题 - 外部属性文件
应用:一些数据库的固定值
1.直接进行配置:连接池
(1)引入数据库的jar包
(2)<bean id="datasource" class="com.mysql.pool.datasource">//连接池对象
<property name ="driverClaaName" value="com.mysql.jdbc.Driver">
<property name="url" value="">
<property name="usernmae">
<property name="password">
</bean>
2.引入外部的属性文件
(1)property格式文件,数据库的基本信息
jdbc.properties
prop.driverClassName=...
prop.url=...
prop.username=...
prop.password=...
(2)引入properties文件到xml配置文件
引入context名称空间;
在spring中使用标签进行引入:<context:properties-placeholder
location="classpath:jdbc.properties"/>
value="${prop.username}"//进行属性的引用
主要是:xml创建对象,xml注入属性
基于注解实现bean管理
-
什么是注解:
(1)代码特殊标识:@注解名称(属性名称=属性值...)
(2)在类上,方法上,属性上面均可以使用注解
(3)让配置更加简介,更加直观 -
bean管理创建对象的注解:
(1)@Component: 创建对象
(2)@Service:业务层
(3)@Controller:web
(4)@Respository:dao
功能都一样:创建对象,在不同的场景使用不一样的注解是有利于理解 -
基于注解进行对象创建
(1)开启组件扫描:<context:component-scan base-package="com.lcc"></context:component-scan>(2)在类上面写注解
@Service(value = "userService") //value属性值可以省略,默认是类名称,首字母小写。 public class UserService { public void add(){ System.out.println("service add......."); } }
开启组件扫描
use-default-filters="false"
表示使用自己配置的filter
<context:component-scan base-package="com.lcc" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
注入属性
常用注解:对象属性的注入,普通类型的注入(@Value)
命名
@Repository(value = "user")
- @AutoWired:根据类型自动注入(Bytype)
//1、在service和dao中创建相应的注解
//2.在service中注入dao对象
@Autowired
private userDao userDao;
- @Qualifier(根据属性名称自动注入)
//如果一个类型会有多个实现的名字,会产生错误
@Autowired
@Qualifier(value = "user")
- @Resource(可以根据名称或者属性注入)
@Resource//默认根据类型进行注入
//根据名称注入
@Resource(name = "user")
- @Value:普通注入属性
@Value("lcc")
private String name;
完全注解开发
- 创建配置类,替代xml配置文件
@Configuration//替代配置类
@ComponentScan(basePackages = {"com.lcc"})//开启包扫描
public class springConfig {
}
测试类
@Test
public void test02(){
ApplicationContext applicationContext=new AnnotationConfigApplicationContext(springConfig.class);
UserService userService = applicationContext.getBean("userService", UserService.class);
System.out.println(userService);
userService.add();
}
核心部分2 AOP
AOP的概念
定义:面向切面编程,可以对业务逻辑部分进行隔离,提高程序的可重用性,降低耦合度。
graph TD
登录功能 -->输入用户名密码-->查询数据库-->判断-->进入主页面
在登陆上增加权限判断,普通用户和管理员
- 原始方式:修改源代码
- 不修改源代码,增加新的功能,权限判断模块单独写,配置到原来有的登录上-->AOP
AOP底层原理
- AOP面向切面编程,AOP的底层使用动态代理,增强功能
有两种情况:
(1)有接口的情况:使用JDK的动态代理
(2)没有接口的情况:使用CGLIB的动态代理
动态代理:
- 有接口:Jdk的动态代理实现:
interface userDao{
public void login();
}
class UserDaoImpl implements userDao{
public void login(){
//登录的过程
}
}
(1)创建userDao接口实现类的代理对象,通过代理对象增强功能。
2. 没有接口的情况:使用CGLIB的动态代理:创建当前user类的子类的代理对象,通过代理对象进行功能增强。
class user{
public void add(){
...
}
}
class Person extends user{
public void add(){
super.add();
//增强逻辑
...
}
}
AOP底层原理
- 使用JDK的动态代理,使用Proxy创建代理对象。
(1)调用newProxyInstance(ClassLoader loader(类加载器),interfaces(支持的接口),InvocationHandler h(增强的逻辑))
package com.lcc.dao;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class JDK{
public static void main(String[] args) {
Class[] interfaces={userDao.class};
/* Proxy.newProxyInstance(JDK.class.getClassLoader(), interfaces, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
});*/
userDaoImpl userDao=new userDaoImpl();
userDao o = (com.lcc.dao.userDao) Proxy.newProxyInstance(JDK.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
o.add();
System.out.println();
}
}
class UserDaoProxy implements InvocationHandler{
//将创建谁的代理对象,将对象传递过来
//通过有参构造传递
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 invoke = method.invoke(object, args);
//方法之后
System.out.println("方法之后执行");
return null;
}
}
AOP操作术语
- 连接点:哪些方法可以被增强,都被称为连接点(理论上)
- 切入点:实际被增强的方法
- 通知,增强:实际增强的部分,通知有多种类型,前置,后置,环绕,异常,最终通知
- 切面:是一个动作上的操作,将通知应用到切入点的过程就是切面。
实现AOP操作
- 基于AspectJ实现AOP操作
- 什么是AspectJ:与spring框架一起使用完成AOP操作。
- 如何实现:
(1)基于xml
(2)基于注解实现
- 引入相关的AOP的依赖
- 切入点的表达式
1.作用:知道对哪个类里面的方法进行增强
2:语法:
execution([权限修饰符][返回类型][类全路径][方法名称][参数列表])
eg:对com.lcc.dao.BookDao里的add进行增强
execution(*com.lcc.dao.BookDao.add(..))
eg:对com.lcc.dao.BookDao里的所有方法进行增强
execution(*com.lcc.dao.BookDao.*(..))
AspectJ注解使用
- 创建类,定义里面的方法
public class User {
public void add(){
System.out.println("add...");
}
}
2.创建增强类,写增强的逻辑:在增强类中,创建方法,让不同方法代表不同通知类型
public class userProxy {
public void before(){
System.out.println("before");
}
}
3.进行通知的配置:
(1).在spring的配置文件中,开启注解扫描
(2).使用注解创建user和userproxy对象
(3).在增强类上增加@Aspect
(4).在spring配置文件中开启生成代理对象
(5).配置不同类型的通知:在增强类的里,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
重用切入点
@Pointcut(value="切入点表达式"),通过方法名进行相同切入点的应用。
多个增强类对同一方法进行增强,设置优先级,看谁先执行
@Oder(1)数值小就越先执行
AspectJ的配置文件
JdbcTemplate---Jdbc模板
定义:
- SPring对jdbc的封装,实现对数据库的操作 准备工作
- 引入jar包,引入依赖
- 配置文件中配置连接池,datasource
- 配置jdbcTemplate对象,注入datasource,
- 在dao类中注入jabctemplate对象,并使用。
JDBCTemplate
//操作数据库
//对应数据库表创建实体类
@AutoWired
priavte JDBCTemplate jdbcTemplate;
//添加
public void add(Book book){
//update可是实现添加,修改,delete参数
String sql = "insert into book values(?,?,?)";
jdbcTemplate.update(sql,book.getId(),book.getName(),book.getUsatus());
//参数是可变参数
}
//实现查询操作
//查询返回某个值
public int selectCount(){
int res=0;
String sql="select count(*) from user"
Integer count=jdbcTemplate.queryForObject(sql,Integer.class);
res=count;
return res;
}
//返回某个对象
//RowMapper是一个接口,返回不同类型数据,使用这个接口里面实现类完成数据的封装。
public T select(String id){
String sql="select * from user where userId=?"
T t=jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<T>(T.class),id);
return t;
}
//返回集合
public List<T> selectList(){
String sql="select * from user"
List<T> t=jdbcTemplate.query(sql,new BeanPropertyRowMapper<T>(T.class));
return t;
}
RowMapper是一个接口,返回不同类型数据,使用这个接口里面实现类完成数据的封装。
事务处理
- 事务:是数据库操作的最基本单位,逻辑上一组操作,要么都成功,要么都失败
- 事务的特性:ACID
- 原子性:要么都成功
- 一致性:操作之前和操作之后的总量是不变的
- 隔离性:多事务操作的时候,不会产生影响
- 持久性:提交之后,表的数据会发生变化。
spring操作事务
- 操作过程:一般在service中进行事务的操作
- 开启事务操作
- 业务操作
- 对异常进行捕获,回滚
- 没有异常,提交异常
- 在spring中有编程式和声明式处理(基于xml,基于注解方式) 声明式使用到了AOP原理
事务管理器 PlatFormTransactionManager
注入对象
<bean id="TranscationManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">
</property>
</bean>
开启事务注解
<tx:annotation-driven transaction-manager="TranscationManager"></tx:annotation-driven>
在service类中添加事务注解
@Transactional
//可以添加到类上,也可以式方法上
事务操作之参数配置
- progation:事务传播行为:多事务进行修改时,应该是怎么处理
- ioslation:事务隔离级别
- timeout:超时时间
- readOnly:是否只读
- rollbackFor:回滚
xml配置
<aop:config>
//配置切入点
<aop:pointcut id="pt" expression="execution(* com.lcc.service.UserService.*(..))"/>
//配置切面
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
</aop:config>
课程总结
- Spring框架概念
- 为了解决企业复杂性,两个核心组成:IOC和AOP
- IOC容器
- IOC底层原理:工厂和反射
- BeanFactory
- IOC操作Bean管理(基于xml)
- IOC操作Bean管理(基于注解)
- AOP
- AOP底层原理:动态代理
- 切入点,增强,通知,切面
- AspectJ实现AOP的操作
- JdbcTemplate
- 使用jdbcTemplate实现对数据库的CURD的操作
- 实现对数据库的批量操作
- 事务管理
- 事务的概念,和特性
- 声明事务管理基于注解方式实现