Spring:是一个轻量级的IOC和AOP的java开发框架,为了简化企业级开发而生。核心就是控制反转和面向切面编程。
IOC:控制反转(Inverse of Control),以前项目都是在哪儿用到对象 在哪儿new,把生成对象的权利反转给spring,让spring把对象管理起来,在哪用在哪注入。
AOP:面向切面编程。可以对业务逻辑和非业务逻辑进行隔离,将程序中的一些非业务代码进行提取,然后让代理对象去调用公共的方法,就可以做到在不需要修改原来代码的情况下,为程序添加额外的功能,从而使得各部分之间的耦合度降低,提高程序的可重用性。好处就是:减少重复,专注业务;
底层实现:使用的是动态代理模式。是通过一个代理对象来实现对非业务代码进行调用的。告诉代理对象,调用哪个方法时,让代理对象去帮助我们调用哪个方法。
AOP思想不是spring框架特有的,只是spring框架引入使用了这一思想。
非业务代码使用案例:
jdbc自动事务提交,mybatis事务默认不自动提交,需要我们在程序中手动提交 sqlsession.commit();spring框架把提交事务的功能帮助我们管理起来了,封装好了。
保障一个事务中的多条sql,要么都执行,要么都不执行,只要有发生异常就回退到事务开始未进行操作的状态,(例如转账)@Transactional
@Transactional标签的用法:
即然是传播,那么至少有两个方法才可以发生传播。
事务传播行为:A事务方法调用B事务方法时,B事务是一个独立的事务呢(独立的,表示B出现了问题,不影响A)?还是B事务合并到A事务中呢(B影响A,A影响B)?这就是由B的事务传播行为决定的。
是Spring框架独有的事务增强特性,不属于事务实际提供者mysql。
Spring 定义了七种传播行为:
事务传播行为类型 | 说明 |
---|---|
PROPAGATION_REQUIRED | 如果A有事务, B加入到A事务中;如果A没有事务,B就新建一个事务,与A没有关系。(常见) |
PROPAGATION_REQUIRES_NEW | 无论A是否有事务,B都会创建新的事务(独立的) |
PROPAGATION_SUPPORTS | 支持A事务;如果A没有事务,B就以非事务方式执行 |
PROPAGATION_NEVER | B以非事务方式执行;如果A存在事务,则抛出异常。 |
PROPAGATION_MANDATORY | 使用A事务,如果A没有事务,就抛出异常。 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务, 则执行与 PROPAGATION_REQUIRED 类似的操作。 |
注意:事务传播行为不能是同一个类中的方法相互调用,必须是一个类中的方法调用另一个类中的方法
单例模式、工厂模式、原型模式、代理模式。自己补充其他的几种
BeanFactory和ApplicationContext都是spring中定义的上层的接口,ClassPathXmlApplicationContext类是spring框架的底层的实现。
BeanFactory接口是spring中最顶层的接口,定义bean管理的基本方法;ApplicationContext接口继承了BeanFactory,在此基础上进行功能的扩展。
区别:
平常说的Ioc容器、spring容器都是比较宏观的,对spring管理对象的称呼。Spring中常用容器,指的是具体实现IOC功能的类。
现在使用的是实现了ApplicationContext接口的具体实现类,下面有两个具体的实现类:
WebApplicationContext是ApplicationContext的子接口,主要是用于Web应用。
AnnotationConfigApplicationContext中是不需要配置 XML 配置文件。
BeanFactory是整个Spring IOC容器的核心,是定义如何管理bean。
FactoryBean也是一个接口,用来为具体创建对象的工厂进行功能定义。
把交给spring容器管理的对象称为bean对象,与自己的new的对象有所不同。
spring管理的bean生命周期问题:spring管理的bean,从诞生到销毁的整个过程。可以分为5个阶段:
回顾一下servlet,经常还有问到servlet是线程安全的吗?
class XXXServlet{
int count = 0; //本意是每次请求中都可以使用一个自己的count
//但是在serlvet中不可以做到,因为serlvet对象是单实例
doGet(){
}
}
Spring的bean作用域(scope)类型:
如果spring中的bean(xxxController..)是原型bean,那么每次请求到来时都会创建一个新的对象,不会存在数据共享,就是线程安全的。
如果spring中的bean是单例的,所有线程都共享一个对象,就会存在线程安全问题。但也不是绝对的,分情况。bean又分为
public class UserService {
int num = 0;
User user;//可以用来为每次请求存储数据 那么就是有状态的, 就会出现线程安全问题
UserDao userDao;//只是用来负责调用对象中的方法,不存储数据 也是无状态的 是线程安全的
}
如何解决有状态bean的线程安全问题?
没有使用spring依赖注入,是不会有问题的。只是简单的创建A和B的对象,A类中b属性和B类中a属性都为null。
class A{
B b;
}
class B{
A a;
}
一旦使用了spring框架的自动注入,就会出现循环依赖问题。A创建时-->需要B----B去创建--->需要 A,从而产生了循环。
class A{
@Autowired //自动注入注解, 当创建A类对象时,就需要为b属性注入值.
B b;
}
class B{
@Autowired //自动注入注解, 当创建B类对象时,就需要为a属性注入值.
A a;
}
spring内部有三级缓存:三级缓存其实就是3种map,分别用来存储不同的对象。
3个map分别用来存储:
将处于不同阶段的bean对象进行分别的存储,以达到先将一个对象初始化完成,再初始化另一个对象。
Spring解决循环依赖问题:首先采用实例化,属性注入分离的策略。
过滤器是javaweb(servlet)中的规范,它是在请求进入到servlet之前进行拦截,可以拦截所有进入到web后端的请求。
拦截器是spring框架中封装的,只能拦截进入到controller中的请求。
@Component:泛指各种组件。@Controller、@Service、@Repository都可以称为@Component
@RestController,组合的注解,里面包含两个注解:
@Scope设置类型包括:设置 Spring 容器如何新建 Bean 实例
@Autowired:由Spring提供
@Qualifier:当有多个同一类型的 Bean 时,可以用@Qualifier(“name”)来指定。与@Autowired 配合使用。
@Resource:由 java 提供
Spring支持AspectJ的注解式切面编程
@Aspect:声明一个切面
@After:在方法执行之后执行(方法上)
@Before:在方法执行之前执行(方法上)
@Around:在方法执行之前与之后执行(方法上)
@PointCut:声明切点
@EnableAspectJAutoProxy:开启Spring对AspectJ代理的支持
@RestController:该注解为一个组合注解,相 当于@Controller和@ResponseBody的组合,注解在类上,意味着,该Controller的所有方法都默认加上了@ResponseBody。
@RequestMapping:用于映射 web 请求,包括访问路径和参数
@ResponseBody:支持将返回值放到 response 内,而不是一个页面,通常用户返回json数据
@RequestBody:允许request的参数在request体中,而不是在直接连接的地址后面。
@Transactional:注解放在类级别时,表示所有该类的公共方法都配置相同的事务属性信息。
@SpringBootApplication里面包含三个注解标签:
@Confiquration用于配置类上面
@Bean在配置类的方法上,表示此方法会返回一个bean,交给spring框架,替代xml中的方式。
@RestControllerAdvice,@ExceptionHandler 用于统一异常处理,捕获指定的异常.
sprinaboot是对spring框架的搭建进行简化,去掉xml配置文件,内置tomcat(容器)。
起步依赖(可以将相关的jar包自动依赖进来)
自动配置(自动装配):在springboot项目中,只需要添加一个组件的依赖(jar),springboot就会自动将这一组件进行装配,可以让我们在程序中直接使用。(例如redis,只需要添加依赖,可以注入使用Redistemplate)。
springboot是基于约定大于配置的思想。
注解、以及底层类对pom.xml进程读取,读取完后找到组件对应配置类。
1.在启动类上有一个@SprinqBootApplication注解,它是一个复合注解标签,里面包含三个注解标签:
2.@EnableAutoConfiquration注解标签中包含@Import({AutoConfigurationImportSelector.class)注解,其中包含一个类AutoConfigurationImportSelector,此类是根据pom.xml文件中配置来进行组件的加载(例如配置redis、mail等依赖)。
3.根据pom.xml文件中的依赖的配置,去jar包的spring.factories文件中,找到组件对应配置类,对配置类进行加载。
4.在程序中可以直接注入使用。
总结:首先依赖启动类的注解标签,注解标签底层有具体的实现类,对pom.xml文件进行读取,找到对应组件的配置类,再在applcation.yml文件读取组件需要的配置信息,最终完成装载。