Spring入门笔记
IOC容器
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
-
IOC底层原理
- xml解析、工厂模式、反射
通过解析xml获取对象属性值,在工厂模式中通过反射创建对象
- xml解析、工厂模式、反射
-
IOC接口(BeanFactory)
-
IOC思想基于IOC容器完成,IOC容器底层就是对象工厂。
-
Spring提供IOC容器实现的两种方式(两个接口):
- BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员使用
- 加载配置文件时不会创建对象,在获取(使用)对象时才创建 - ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用
- 加载配置文件时就会将配置文件中的对象进行创建
- BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员使用
-
ApplicationContext接口的实现类
FileSystemXmlApplicationContext代表读取磁盘下的配置文件
ClassPathXmlApplicationContext代表读取类路径下的配置文件
-
-
IOC操作 Bean管理
Bean管理指Spring创建对象、Spring注入属性
Bean生命周期
- 通过构造器创建bean实例(无参构造器)(实例化)
- 为bean的属性设置值和其他bean引用(调用set方法)(属性赋值)
- 将bean实例传递bean后置处理器的方法 postProcessBeforeInitialization
- 调用bean的初始化方法(需要进行配置)(初始化)
- 将bean实例传递bean后置处理器的方法 postProcessAfterInitialization
- bean对象获取(调用)
- 当容器关闭时,调用bean的销毁方法(需要进行配置销毁方法)(销毁)
代码:
package com.lee.spring1;
public class User {
private String name;
public User() {
System.out.println("无参构造方法执行。。。。。。");
}
public void setName(String name) {
this.name = name;
System.out.println("set方法执行。。。。。。");
}
public void initMethod(){
System.out.println("初始化方法执行。。。。。。。");
}
public void destroyMethod(){
System.out.println("销毁方法执行。。。。。。");
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
@Test
public void testBeanLife(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
User user = context.getBean("user", User.class);
System.out.println(user);
context.close();
}
<bean id="user" class="com.lee.spring1.User" init-method="initMethod" destroy-method="destroyMethod">
<property name="name" value="小岛元太"></property>
</bean>
输出结果:
- 基于Xml创建对象
- 在Spring配置文件中,使用Bean标签,标签里面添加对应属性
-
- id属性:唯一标识
- class属性:类全路径(包括类路径) - 创建对象时,默认执行无参构造方法完成对象创建
- 基于xml注入属性
-
DI:依赖注入,即属性注入
- 使用set方法进行注入
①创建类,为属性创建set方法
②在Spring配置文件配置对象创建,配置属性注入
- 使用有参数的构造方法进行注入 ①创建类,创建有参构造方法 ②在Spring配置文件配置对象创建,配置属性注入 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201204183849939.jpg#pic_center) - p名称空间注入(了解) ①添加p名称空间
-
②进行属性注入,在bean标签里面进行操作
- 注入其他类型属性
- 注入外部bean
- 注入属性-内部bean和级联赋值
此处打印显示透子是公安,同时可以说明配置文件的优先级。
- 注入集合类型属性
- 基于注解
- Spring针对Bean管理中创建对象提供的注解
- @Component
- @Service
- @Controller
- @Repository
以上注解功能一样,都可以用来创建bean实例 - 步骤
- 引入依赖
- 开启组件扫描
<!--开启组件扫描-->
<context:component-scan base-package="com.lee"></context:component-scan>
- 基于注解方式实现属性注入
- @AutoWired:根据属性类型进行自动装配(一个接口有多个实现类时报错)
- @Qualifier:根据属性名称进行注入
- @Resource:可以根据类型注入,也可以根据名称注入
- @Value:注入普通类型属性
- 完全注解开发
@Configuration
@ComponentScan(basePackages = {"com.lee"})
public class SpringConfig{
}
AOP
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
public interface UserDao {
String update(String id);
}
public class UserDaoImpl implements UserDao {
public String update(String id) {
System.out.println(id);
return id;
}
}
public class UserProxy implements InvocationHandler {
private UserDao userDao;
public UserProxy(UserDao userDao){
this.userDao = userDao;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法执行前:" + method.getName() + "参数:" + Arrays.toString(args));
method.invoke(userDao,args);
System.out.println("方法执行后。。。。。。");
return null;
}
}
public static void main(String[] args) {
UserDao userDao = new UserDaoImpl();
UserDao userProxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), new Class[] {UserDao.class},new UserProxy(userDao));
userProxy.update("!!!!!!!!!===========!!!!!!!!");
}
- 无接口的情况,使用CGLIB动态代理
-
AOP操作术语
-
连接点:类中可以被增强的方法成为连接点
-
切入点:实际被真正增强的方法
-
通知(增强):
- 实际增强的逻辑部分称为通知(增强)
- 通知的类型
①前置通知
②后置通知
③环绕通知
④异常通知
⑤最终通知
- 通知的类型
- 实际增强的逻辑部分称为通知(增强)
-
切面:
- 把通知应用到切入点的过程
-
-
AOP操作
-
Spring框架一般都是基于AspectJ实现AOP操作,AspectJ不是Spring的组成部分,独立AOP框架,一般把AspectJ和Spring一起使用,进行AOP操作
-
基于AspectJ实现AOP
切入点表达式
- 基于xml配置文件实现
①创建增强类与被增强类
②在Spring配置文件中创建类对象
③在Spring配置文件中配置切入点
<bean id="book" class="com.lee.spring1.aopxml.Book"></bean>
<bean id="bookProxy" class="com.lee.spring1.aopxml.BookProxy"></bean>
<aop:config>
<!--切入点-->
<aop:pointcut id="p" expression="execution(* com.lee.spring1.aopxml.Book.buy(..))"></aop:pointcut>
<!--配置切面-->
<aop:aspect ref="bookProxy">
<!--增强作用在具体方法上-->
<aop:before method="before" pointcut-ref="p"></aop:before>
</aop:aspect>
</aop:config>
- 基于注解方式实现
①创建类,在类里定义方法
②创建增强类(编写增强逻辑)
③进行通知配置
-在Spring配置文件中,开启注解扫描
-使用注解创建Xxx和XxxProxy对象
-在增强类上面添加注解@Aspect
-在Spring配置文件中开启生成代理对象
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
④配置不同类型的通知
@Before(前置通知)、@After(最终通知)、@AfterReturning(后置通知)、@AfterThrowing(异常通知)、@Around(环绕通知)
⑤相同切入点抽取
@Pointcut
⑥多个增强类对一个方法进行增强时,设置优先级
@Order(数字类型),数字类型值越小优先级越高
事务管理
-
事务(Transaction)
-
一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transaction和end transaction语句(或函数调用)来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。
-
ACID
- 原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
- 一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
- 隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
-
Spring事务管理介绍
-
事务配置参数
-
propagation:事务传播行为
-
isolation:事务隔离级别
- 事务隔离级别
-
- Spring事务隔离级别
**DEFAULT**:使用数据库本身使用的隔离级别 ORACLE(读已提交) MySQL(可重复读)
**READ_UNCOMITTED**:读未提交(脏读)最低的隔离级别,一切皆有可能。
**READ_COMMITED**:读已提交,ORACLE默认隔离级别,有幻读以及不可重复读风险。
**REPEATABLE_READ**:可重复读,解决不可重复读的隔离级别,但还是有幻读风险。
**SERIALIZABLE**:串行化,最高隔离级别,杜绝一切隐患,缺点是效率低。
- [ ] timeout:超时时间
- [ ] readOnly:是否只读
- [ ] rollbackFor:哪些异常回滚
- [ ] noRollbackFor:哪些异常不回滚
-
事务添加到JavaEE三层结构里面Service层
-
在Spring进行事务管理操作
- 编程式事务管理、声明式事务管理
-
声明式事务管理
- 基于注解方式
-
在Spring配置文件配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
- 在Spring配置文件开启事务注解
①引入事务名称空间
②开启事务注解
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
-
添加事务注解@Transactional
-
基于xml配置文件方式
-
配置事务管理器
-
配置通知
```xml
<tx:advice id="txadvice">
<!--配置事务参数-->
<tx:attributes>
<!--指定哪种规则的方法上面添加事务-->
<tx:method name="account*"/>
</tx:attributes>
</tx:advice>
```
- 配置切入点和切面
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.lee.spring1.service.UserService.*(..))"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
</aop:config>
-
在Spring进行声明式事务管理,底层使用AOP
-
Spring事务管理API
- 提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同实现类
- 提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同实现类
Spring5新特性
- Spring5.0框架自带了通用日志封装
- Spring5移除了Log4jConfigListener,官方建议使用Log4j2
- Nullable注解和函数式注册对象
- @Nullable
- 函数式风格GenericApplicationContext
- Spring5支持整合junit5
- Webflux
- 待续…