Spring5
1、Spring
-
什么是Spring?
Spring是轻量级的开源的JavaEE框架
IOC:控制反转,把创建对象的过程交给Spring进行管理
AOP:面向切面,不修改源代码进行功能增强
-
为什么需要Spring?
Spring可以解决企业应用开发的复杂性,有以下特点:
- 方便解耦,简化开发
- AOP编程支持
- 方便程序测试
- 方便和其他框架进行整合(粘合剂)
- 方便进行事务操作
- 降低API开发难度
-
怎么使用Spring?
- 创建普通类(User)
- 创建Spring配置文件(applicationContext.xml),在配置文件配置创建的对象
<bean id="user" class="com.atguigu.spring5.User"></bean>
1. 测试代码编写
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
applicationContext.getBean("user");
2、IOC
-
什么是IOC?
控制反转,把对象的创建和对象之间的调用过程,交给Spring进行管理
-
为什么需要IOC?
为了降低耦合度
-
怎么使用IOC?
Spring提供IOC容器实现两种方式:(两个接口)
-
BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用
加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象(懒加载)
-
ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用
加载配置文件时候就会创建好对象放入IOC容器(预加载)
-
3、FactoryBean
-
什么是FactoryBean?
Spring有两种类型bean,一种普通bean,另外一种工厂bean(FactoryBean)
普通bean:在配置文件中定义bean类型就是返回类型
工厂bean:在配置文件定义bean类型可以和返回类型不一样
-
为什么需要FactoryBean?(主要和beanFactory对比)
我们使用beanFactory获取bean(getBean())之前,我们需要事先定义这个bean长什么样子,或者说它由哪些组件组成,这种方式的弊端是所有的bean都需要实现定义好,但是有时候,有的一些bean我们只知道它大概是什么样子,但是无法事先定义出其具体的功能,只有在代码执行的时候,我才知道是什么类型,需要实现什么功能,例如mybatis中的mapper,这样FactoryBean就有了其意义,它可以定义出一种类型的Bean,并且在创建的时候再去实现其具体的功能。
-
怎么使用FactoryBean?
- 第一步:创建类,让这个类作为工厂bean,实现接口FactoryBean
- 第二步:实现接口里面的方法(主要是getObject来返回获取到的对象类型),在实现的方法中定义返回的bean类型
public class MyBean implements FactoryBean<Course>{
**@Override
public Course getObject() throws Exception(){
Course course = new Course();
course.setCname("abc");
return course;
}**
...//其他重写的方法
}
1. 这样定义后通过ioc容器getBean()获取MyBean对象时获取的是Course对象(准确来说是容器创建的代理对象)。
2. 如果想获取到MyBean对象,可以在getBean()方法调用时在这样写getBean("&myBean")。
4、IOC容器中singleton和prototype的区别
-
singleton单实例,prototype多实例
-
设置scope值是singleton的时候,加载spring配置文件的时候就会创建单实例对象(加载即创建);
设置scope值是prototype的时候,不是在加载spring配置文件的时候创建对象,而是在调用getBean方法的时候创建多实例对象
5、IOC操作Bean管理(bean生命周期)
-
bean生命周期(主观来看)
- 通过构造器创建bean实例(无参构造器)
- 为bean的属性设置值和对其他bean引用(调用set方法)
- 调用bean的初始化方法(需要进行配置初始化的方法)
- bean可以使用了(对象获取到了)
- 当容器关闭的时候,调用bean 的销毁方法(需要进行配置销毁的方法)
-
bean的后置处理器,bean生命周期有七步(内部大致调用过程)
- 通过构造器创建bean实例(无参构造器)
- 为bean的属性设置值和对其他bean引用(调用set方法)
- 把bean实例传递给bean后置处理器的方法postProcessBeforeInitialization
- 调用bean的初始化的方法(需要进行配置初始化方法)
- 把bean实例传递给bean后置从处理器的方法postProcessAfterInitialization
- bean可以使用了(对象获取到了)
- 当容器关闭的时候,调用bean的销毁方法(需要进行配置销毁的方法)
6、IOC操作Bean管理(基于注解方式)
-
什么是注解?
注解是代码特殊标记,格式:@注解名称(属性名称1=属性值1,属性名称2=属性值2...)
-
为什么要使用注解?
简化xml配置
-
在哪里使用注解?
注解作用在类上面,方法上面,属性上面
-
怎么使用注解?
-
在对应类上标上对应的注解
@Component
@Controller
@Service
@Repository
-
在spring配置文件中开启组件扫描
-
<!-- 扫描com.atguigu中的所有组件放入容器 -->
<context:component-scan base-package="com.atguigu">
</cotext:component-scan>
7、AOP(面向切面)
-
什么是AOP?
- 面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
- 通俗描述:不通过修改开发人员写的源代码的方式,在主干功能里面添加新功能。
-
为什么要使用AOP?
使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
-
底层原理(两种情况)
-
有接口的情况,使用JDK动态代理
创建接口实现类代理对象,增强类方法
-
没有接口情况,使用CGLIB动态代理
创建子类的代理对象,增强类方法
注:想了解详情看《Spring5框架笔记》
-
-
怎么使用AOP?
-
AOP术语:
-
连接点:类里面哪些方法可以被增强,这些方法称为连接点
-
切入点:实际被真正增强的方法,称为切入点
-
通知(增强):
(1)实际增强的逻辑部分称为通知(增强)
(2)通知类型有5种
前置通知 后置通知 环绕通知 异常通知 最终通知
-
切面:是动作。把通知应用到切入点的过程
-
-
AOP操作准备工作:
(1)Spring框架一般都是基于AspectJ实现AOP操作
AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作
(2)基于AspectJ实现AOP操作
基于xml配置文件实现
基于注解方式实现(使用)
(3)在项目工程里面引入AOP相关依赖
(4)写切入点表达式
切入点表达式作用:知道对哪个类里面的哪个方法进行增强
语法结构:execution([权限修饰符] [返回类型] [类全路径] 方法名称) 如:execution(* com.atguigu.dao.BookDao.*(..))
-
AspectJ注解
① 创建类,在类里面定义方法
② 创建增强类(编写增强逻辑)
-
@Aspect
public class UserProxy{
public void before(){ //前置通知
System.out.println("before...");
}
}
③ 进行通知的配置
在增强类上加@Aspet注解生成代理对象
**在spring配置文件中开启生成代理对象**
<!-- 开启Aspect生成代理对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
1. 配置不同类型的通知
在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
//增强的类
@Component
@Aspect //生成代理对象
public class UserProxy{
//前置通知
//@Before注解表示作为前置通知
@Before(value="execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void before(){
System.out.println("before...");
}
//后置通知(返回通知)
@AfterReturning(value="execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void afterReturning(){
System.out.println("afterReturning...");
}
//最终通知
@After(value="execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void after(){
System.out.println("after...");
}
//异常通知
@AfterThrowing(value="execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void afterThrowing(){
System.out.println("afterThrowing");
}
//环绕通知
@Around(value="execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("环绕之前...");
//被增强的方法执行
proceedingJoinPoint.proceed();
System.out.println("环绕之后...");
}
}
1. 相同的切入点抽取
//相同的切入点抽取
@Pointcut(value="execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void pointDemo(){}
//那么之前的前置通知可以写为
@Before(value="pointDemo()")
public void before(){
System.out.println("before...");
}
1. 有多个增强类多同一个方法进行增强,设置增强类优先级
在增强类上添加注解@Order(数字),数字值越小优先级越高
1. 完全使用注解开发
创建配置类,不需要创建xml配置文件
@Configuration //让ioc容器知道这是一个配置类
@ComponentScan(basePackages = {"com.atguigu"} //可以写多个包名
@EnableAspectJAutoProxy(proxyTargetClass=true) //开启注解配置AOP
public class ConfigAop{}
1. AspectJ配置文件(第二种方式配置AOP方式)
1、创建两个类,增强类和被增强类,创建方法
2、在spring配置文件中创建两个类对象
<!-- 创建对象 -->
<bean id="book" class="com.atguigu.spring5.aopxml.Book"></bean>
<bean id="bookProxy" class="com.atguigu.spring5.aopxml.BookProxy"></bean>
3、在spring配置文件中配置切入点
<!-- 配置aop增强 -->
<aop:config>
<!-- 切入点 -->
<aop:pointcut id="p" expression="execution(* com.atguigu.spring5.aopxml.Book.buy(..))" />
<!-- 配置切面 -->
<aop:aspect>
<!-- 增强作用在具体的方法上 -->
<aop:before method="before" pointcut-ref="p" />
</aop:aspect>
</aop:config>
8、JdbcTemplate(后面可以使用MyBatis框架代替)
-
什么是JdbcTemplate?
Spring框架对JDBC进行封装,使用JdbcTemplate方便实现对数据库操作
-
怎么使用JdbcTemplate?
1、引入相关jar包
2、在spring配置文件配置数据库连接池
<!-- 1、导入dbconfig.properties文件 -->
<context:property-placeholder location="classpath:dbconfig.properties" />
<!-- 2、数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="${jdbc.jdbcUrl}" />
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 3、配置JdbcTemplate对象,注入DataSource -->
<!-- JdbcTemplate对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 注入dataSource -->
<property name="dataSource" ref="dateSource" ></property>
</bean>
9、事务操作(搭建事务操作环境)
-
什么是事务?
事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败
-
事务四个特性
- 原子性
- 一致性
- 隔离性
- 持久性
-
怎么使用(开启)事务?
1、事务添加到JavaEE三层结构里面的Service层(业务逻辑层)
2、在Spring进行事务管理有两种方式:
编程式事务和声明式事务
3、声明式事务管理
基于注解方式(使用)和基于xml配置文件方式
4、在Spring进行声明式事务管理,底层使用AOP原理
5、开启事务
1、在spring配置文件配置事务管理器
<!-- 创建事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
2、开启事务注解
<!-- 开启事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
3、在需要开启事务的类上(或者类里面的方法上)添加事务注解
(1)@Transactional,这个注解添加到类上面,也可也添加到方法上面
(2)如果把这个注解添加到类上面,这个类里面所有的方法都添加事务
(3)如果把这个注解添加到方法上面,就只为这个方法添加事务
@Service
@Transactional
public class UserService{}