https://www.cnblogs.com/angelye/p/7506566.html
spring中的IOC:
IOC:Inversion of Control 控制反转
spring中吧每一个需要管理的对象叫 spring Bean(简称Bean) Spring 管理这些bean 的容器 IOC 容器,该容器主要负责 管理各种对象的声明周期(对象的创建、初始化、销毁等)
IOC容器并没有实现更多的功能,但它的存在使我们不需要很多代码、不需要考虑对象间复杂的耦合关系就能从IOC容器中获取合适的对象,而且提供了各种对象的可靠的管理,极大地降低了开发的复杂性。其实就是一种将调用者与被调用者分离的思想(思考web层和service层和dao层的关系) 。
所有的 IOC 容器都需要实现BeanFactory接口,它是一个顶级接口但是功能不是太大 spring 在BeanFactory 接口上设计了ApplicationContext 接口继承了上级接口
IOC 容器中 通过getBean 可以通过类型和名称来获取Bean,默认bean是单列isSingleton
装配你的Bean
spring中允许XML或者Java配置来装配Bean但是SpringBoot是基于注解的方式
spring通过注解 标明那个类扫描进入Spring IOC 容器中 @ComponentScan 采用何种策略去扫描bean
sprng: 通过反射更具
依赖注入:
bean之间的依赖成为依赖注入,
@Autowired 使用的最多的注解根属性的类型(by type) 找到对应的bean进行注入
IOC容器的顶层接口beanFactory 通过getBean获取对应的Bean
当类型有多个属性的时候会产生歧义,动物可以有多种类型
@Resource
作用和@Autowired差不多,只不过 @Resource是默认先用byName,如果找不到合适的就再用byType来注入
@Scope("prototype")
@Component
如果不指定名字的话,默认的bean的名字就是类名首字母小写
把当前的bean 注入到 spring对象中 Scope:指定单列还是 非单列
@Autowired:自动注入
@Autowired注解可以写在成员变量、setter方法、构造器函数上面
@PostConstruct和@PreDestroy
1) 标注了@PostConstruct注解的方法将在类实例化后调用
2) 标注了@PreDestroy注解的方法将在类销毁之前调用
读取属性文件中的内容
@Value("${database.username}")
1.set方式注入(必须依靠set方法)
A:通过setXXX方法为目标的bean 注入关系的依赖方式
B:在spring容器中拿形同名字的对象是同一个对象默认是单列的
可以在在bean标签中加入属性scope="prototype"
可以注入的内容有:
基本类型(8中基本类型+字符串)的装配
对象类型的装配
集合的装配
A:对象类型
name属性表示一个方法 这里是setStudent() ref:是这个方法要用的参数
B:集合的装配 向一个对象中注入集合
Student s = (Student) container.getBean("stu").show();
2构造器注入
两种注入方式的比较:
依赖注入和传统的javaBean相似通过setXxx方法注入更加主观,
构造器注入可以决定注入的顺序,优先依赖的优先注入
6spring容器创建bean的生命周期
首先spring通过我们的配置,如@componentScan这个注解来扫描去找我们的资源定位,这个时候么有实例化,只是将Bean
发布到Spring Ioc 容器中,接下来实例化Bean--依赖注入--
大致分为Bean定义,Bean的初始化,Bean的生存期,Bean的销毁4个部分
Spring上下文中的Bean也类似,如下
1、实例化一个Bean--也就是我们常说的new;
2、按照Spring上下文对实例化的Bean进行配置--也就是IOC注入;
3、如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id值
4、如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(setBeanFactory(BeanFactory)传递的是Spring工厂自身(可以用这个方式来获取其它Bean,只需在Spring配置文件中配置一个普通的Bean就可以);
5、如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文(同样这个方式也可以实现步骤4的内容,但比4更好,因为ApplicationContext是BeanFactory的子接口,有更多的实现方法);
6、如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化结束时调用那个的方法,也可以被应用于内存或缓存技术;
7、如果Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法。
8、如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法、;
注:以上工作完成以后就可以应用这个Bean了,那这个Bean是一个Singleton的,所以一般情况下我们调用同一个id的Bean会是在内容地址相同的实例,当然在Spring配置文件中也可以配置非Singleton,这里我们不做赘述。
9、当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法;
10、最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
-----------------------------------
AOP
是一种约定编程,将一些相同的逻辑抽离出来动态植入
典型列子
spring事务的管理:
事务的执行过程:打开数据库连接然后对其属性进行设置
执行sql语句,如果么有异常提交事务,有异常则回滚事务,
以上步骤中除了sql外其他步骤都是一样的,代码的重复很高
重复的代码分离出来配置成切面类动态植入。我们只需要编写sql
这一步。
日志的输出:
@Aspect: 标注是一个切面类
@Pointcut("execution(* com.savage.aop.MessageSender.*(..))")
@Pointcut("@annotation(com.fs.common.annotation.SysLog)") 这个注解定义切入点
@Around("logPointCut()") 设置通知注解
认识AOP中的一些基本概念,然后在一个一个的例子中,不断的加强对这些概念的理解,同时要能自己表述出每个概念的含义
AOP 面向切面编程
aspect 切面/切面类
切面类:就是我们抽离出来要动态植入的代码
joinPoint 连接点
在spring的aop中只有 类中的方法 可以做连接点,每一个方法都可以是一个连接点.AOP通过动态代理技术把它植入到对应的流程
pointCut 切入点
有时候我们的切面类不单单应用单个方法,也可以是多个类不同方法,
一组连接点的集合
advice 通知/拦截器
前置通知,后置通知,异常通知,环绕通知
adivsor 增强器
用来筛选类中的哪些方法是我们的连接点(哪些方法需要被拦截).
target 需要执行的目标对象
proxy 代理对象
wave 织入
AOP具体使用配置全文日志输出
@Aspect
@Component
public class SysLogAspect {
@Autowired
private SysLogService sysLogService;
@Pointcut("@annotation(com.fs.common.annotation.SysLog)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
//执行方法
Object result = point.proceed();
//执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
//保存日志
saveSysLog(point, time);
return result;
}
private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
com.fs.sys.model.SysLog sysLog = new com.fs.sys.model.SysLog();
SysLog log = method.getAnnotation(SysLog.class);
if(log != null){
//注解上的描述
sysLog.setOperation(log.value());
}
//请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setMethod(className + "." + methodName + "()");
//请求的参数
Object[] args = joinPoint.getArgs();
try{
String params = new Gson().toJson(args[0]);
sysLog.setParams(params);
}catch (Exception e){
}
//获取request
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
//设置IP地址
sysLog.setIp(IPUtils.getIpAddr(request));
//用户名
String username = ((User) SecurityUtils.getSubject().getPrincipal()).getAccount();
sysLog.setUsername(username);
sysLog.setTime(time);
sysLog.setCreateTime(new Date());
//保存系统日志
sysLogService.insert(sysLog);
}
}
这个文章介绍的隔离级别非常详细
spring中的事务一般是 spring Aop 来管理的 应为在事务管理中 除了执行sql之外一些开启事务,事务回滚,发生异常,事务提交, 释放资源这些一般都是比较固定 的所有按照我们AOP的设计思想,可以吧执行SQL之外的步骤分离出来单独实现。
B:生命数据库事务的约定
通过@Transactional 的配置来告诉spring 在什么地方开启事务,在这个配置中可以设置多个属性,最主要的隔离级别,传播属性注解中的属性(value, propagation,isolation,timeout,resdonly,rollbackfor(指定异常回滚)), 这个注解可以放在接口上,也可以放在是实现类中一般是放在实现类中(spring 使用了JDK代理,和CGLIG 代理)要是在接口中就不能转化为CGLIB代理
互联网访问时刻出现高并发的访问(库存问题) 多个线程同时访问数据,很可能出现数据库的不一致,数据库的丢失更新(lost update) 隔离级别是可以压制数据库的丢失更新
DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别
未提交读 :该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。
读写提交 : 该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值
可重复读:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。
串行化 :数据库最高的隔离级别 要求所有的sqla按照一定的顺兴执行
选择隔离级别会以读写提交为主,防止了脏读,不能避免不可重复读和幻读。设计乐观锁来解决这一问题
乐观锁:
原子性:事务里面的操作单元不可切割,要么全部成功,要么全部失败
一致性:事务执行前后,业务状态和其他业务状态保持一致.
隔离性:一个事务执行的时候最好不要受到其他事务的影响
持久性:一旦事务提交或者回滚.这个状态都要持久化到数据库中
不考虑隔离性会出现的读问题
脏读:在一个事务中读取到另一个事务没有提交的数据
不可重复读:在一个事务中,两次查询的结果不一致(针对的update操作)
虚读(幻读):在一个事务中,两次查询的结果不一致(针对的insert操作)
通过设置数据库的隔离级别来避免上面的问题(理解)
read uncommitted 读未提交 上面的三个问题都会出现
read committed 读已提交 可以避免脏读的发生
repeatable read 可重复读 可以避免脏读和不可重复读的发生
serializable 串行化 可以避免所有的问题
propagion
我们处理一批数据可能只有少数数据出现异常 我们不希望将所有的数据都回滚
只是把出异常的数据进行回滚
required: 当前事务存在就沿用当前的事务
requires_new : 无论当前事务是否存在都会创建新事务去运行,新事务可以有
新的隔离级别 完全独立
nested: 当前方法调用字方法, 子方法发生异常值回滚子方法 执行的sql 语句
spring 的事务原理是AOP 而AOP是动态代理,而类中调用是类自身的代理,用一个
service去调用另一service
spring创建Bean 的生命周期过程
https://www.cnblogs.com/kenshinobiy/p/4652008.html