Spring架构初解
这里只记录一些常用的
beans:放着BeanFactory等读取解析配置文件并通过反射实例化对象的代码
core:核心工具类,被所有其它包调用的包
AOP:为spring提供简单的AOP功能
Aspects:外部的AOP,更加细致的AOP使用
ORM:提供记录和对象的映射,为了更方便地操作从数据库获得的记录
JDBC:JDBC是一套Java对数据库的标准,而Spring封装了它,形成了自己的JDBC库
Transaction:提供了事务
Bean与容器
简单的流程
将bean所在文件(JavaConfig,xml,注释)装起来(classPathResource)
(ApplicationContext)容器使用读取器(Reader)解析bean
加载bean(生命周期)到容器
IOC与DI
IOC的意思是控制反转,原来如果一个对象需要另一个对象,那么它会去new一个对象,然后根据自己需要初始化对象,如果不需要了,就把这个对象给赋值null(help GC),现在这些操作全部交给容器了,对象只负责从容器里获取这个对象来用,将对这个对象的很大部分操作都交给容器完成,也就是把主控制权交给容器
DI的意思是依赖注入,也就是在需要对象的地方,只要注明了,容器就会把对象塞到这个变量中。
Bean的装配
以下代码只作理解用,请不要在意bug
xml型配置
1 创建对象
package com
public class A{
public String name;
public String no;
public A(){}
public A(String name){this.name = name;}
public void setNo(){
this.no = no;
}
}
2 在xml中配置属性
<xml .........>
<bean id = "test" class = "com.A">
<!-- constructor-args可省略,省略默认调用无参构造,不省略就会根据找到的
constructor-args集合起来,寻找一个参数相同的有参构造器 -->
<constructor-args name="name" value="小李"></constructor-args>
<!-- 以下这行通过对象中set方法给属性赋值 -->
<property name ="no" value="10086"></property>
</bean>
</xml>
3 读取xml到容器,将bean装配到属性里
class B{
A a;
Application context;
public B{
context = new ClassPathXmlApplicationContext("as.xml");
//根据名字查找bean
A a = context.getBean("test",A.class);
}
}
JavaConfig型配置(SpringBoot使用)
1 创建对象
package com
//从以下四个任选其一,效果都是一样的,value相当于bean id
@Component(value="test")
//@Service
//@Repository
//@Controller
public class A{
//这个相当于bean的property,但是不需要set方法
@Value(value="hello")
public String name;
public String no;
public A(){}
public A(String name){this.name = name;}
public void setNo(){
this.no = no;
}
}
package com
//这个类不注解
public class B{
public String name;
public B(String name){this.name = name;}
}
2 在JavaConfig中配置bean
@Configuration
<!-- 这个注解可以用于扫描组件-->
@ComponentScan(base Package="com")
public class config{
//这个注解创建出来的Bean,id就是这个方法名,也可以通过name自己指定bean id
@Bean
public B b(){
return new B("abc");
}
}
3 读取Configuration到容器,将bean装配到属性里
class C{
//这三个都能完成自动装配,第一个是用id查找,第二个是用类型查找。
//第三个是Java自己的,Spring不推荐,同时支持id和类型
@Qualified(name="test")
//@Autowired
//@Resource
A a;
@Autowired
B b;
}
p命名空间型
是xml型变种,不重要,知道有即可
Bean的生命周期
1 如果允许循环依赖,创建BeanFactory,将其加入缓存中
2 属性注入
3 调用相关Aware接口(用于取出上下文的东西到对象成员,如beanId或BeanFactory)
4 调用后置处理器的前置方法
5 调用init-Method,init-Method只能是写在该类里的方法
6 调用后置处理器的后置方法
7 正常运行
8 容器关闭或者调用自定义的destroy()
Spring解决循环依赖
Singleton时构造方法导致
class A{
B b;
public A(B b){
this.b = b;
}
}
class B{
C c;
public B(C c){
this.c = c;
}
}
class C{
A a;
public C(A a){
this.a = a;
}
}
存在当前创建bean池,如果构造方法相互依赖,会在池中发现自己,然后报BeanCurrentlyInCreationException
如A创建bean发现需要B,加入池并创建B的bean,B发现需要C,把自己加入池,C需要A时,发现A已经在池就会报错
Singleton时set方法导致
class A{
B b;
public void setB(B b){
this.b = b;
}
}
class B{
C c;
public void setC(C c){
this.c = c;
}
}
class C{
A a;
public void setA(A a){
this.a = a;
}
}
当完成构造方法构造bean时,就会在缓存中保存未完成注入的Object,这样其它类就可以直接通过get()获得,所以不会导致循环依赖
prototype作用域
直接禁止依赖注入,从而防止循环依赖
事务
属性配置
事务的传播性:
@Transactional(propagation=Propagation.REQUIRED)
事务的隔离级别:
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
读取未提交数据(会出现脏读, 不可重复读) 基本不使用
只读:
@Transactional(readOnly=true)
该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。
事务的超时性:
@Transactional(timeout=30)
回滚:
指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)
指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
传播等级
Propagation.REQUIRED 如果外层有事务,使用外层的事务。否则自建事务。
Propagation.REQUIRED_NEW 无论如何都会新建事务
Propagation.SUPPORTED 不会新建事务,但是支持外层事务
Propagation.NOT_SUPPORTED 不会新建事务,会挂起外层事务执行
Propagation.NEVER 不会新建事务,外层有事务直接报错
Propagation.MANDATORY 不会新建事务,外层没有事务直接报错
Propagation.NESTED 增加一个回滚点,如果内层有报错,并且异常在回滚范围内,就会在该点回滚而不会回到初始状态
隔离机制
和mysql相同
失效情况
数据库不支持事务
没有注册进容器
内部自调用导致事务拦截方法没有生效
事务方法不是public级
指定的异常类没有包含报出的异常(默认为RunTimeException)
参考
《Spring源码深度解析》
事务 https://www.cnblogs.com/mseddl/p/11577846.html