Spring相关

Spring

一. Spring家族的介绍

1.1 如何选择框架

  • 对应的开发者社区是否有名,是否活跃
  • 框架的模块是否迭代

1.2 家族体系

  • 主要的部分:
    • Spring Core
    • Spring Data
    • Spring Boot
    • Spring Security
    • Spring Session
    • Spring Intergration
    • Spring REST Docs
    • Spring AMQP
    • Spring Cloud

二. IOC

2.1 IOC(Inversion of Control): 控制反转

  • Spring Core最核心的部分
  • 需要先了解依赖注入(Dependency Inversion)

2.2 依赖注入

  • 为什么要用依赖注入?

    • 传统的方式是底层决定了上层,如果底层发生改变则所有的都需要改变;这样显然是极大的消耗性能的;
  • 使用依赖注入的好处?

    • 把底层类作为参数传递给上层类,实现上层对下层的"控制";

未使用依赖注入的时候,比如一个行李箱的设计,是通过轮子的大小,然后定制出底盘大小,通过底盘和轮子又定制出箱体的大小;如果轮子发生了改变则所有的都无法使用了;
使用依赖注入的时候,首先给一个行李箱的概念,通过注入箱体,底盘和轮子的参数然后构造出一个合适的箱体,当轮子或者其他发生改变了,则也可以直接变化;

2.3 IOC、DI、DL的关系

  • 图示:
    在这里插入图片描述

2.4 实现依赖注入的方式:

  • Setter
  • Interface 实现接口
  • Constructor 构造函数
  • Annotation 基于注解

依赖倒置原则,就是本来是底层决定上层改为从上层影响下层;这部分被隐藏掉了,我们只看到了实例被创建出来,不需要去了解它如何创建的;

2.5 Spring IOC支持的功能

  • 依赖注入
  • 依赖检查
  • 自动装配
  • 支持集合
  • 指定初始化方法和销毁方法
  • 支持回调方法

最核心的功能是依赖注入和自动装配

2.6 Spring IOC容器的核心接口

  • BeanFactory:
    • BeanDefinitionRegistry:提供向IOC容器注册BeanDefinition对象的方法
    • 它是Spring框架最核心的接口
      • 提供IOC的配置机制
      • 包含Bean的各种定义,便于实例化Bean
      • 建立Bean之间的依赖关系
      • Bean生命周期的控制
  • ApplicationContext

BeanFactory是Spring框架的基础设施,面向Spring;ApplicationContext面向使用Spring框架的开发者;

2.7 ApplicationContext的功能(继承多个接口)

  • BeanFactory:能够管理、装配Bean
  • ResourcePatternResolver:能够加载资源文件
  • MessageSource:能够实现国际化等功能;
  • ApplicationEventPublisher:能够注册监听器,实现监听机制;

2.8 分析加入Bean

@Configuration 
public class ApplicationConfig{
	@Bean(name="person")
	public Person initPerson(){
		Person user=new Person();
		user.setId(1L);
		user.setName("Jack");
		return user;
	}
}

在这里的代码中:使用@Configuration注解加入IOC容器,而@Bean注解则配置了一个Bean,如果不指定name,则默认为initPerson作为key[Bean的名称];

  • 启动实例
@SpringBootApplication
public class FrameworkApplication{
	public static void main(String[] args){
		ApplicationContext ctx=SpringApplication.run(FrameworkApplication.class);
		Person person=ctx.getBean(Person.class);
		System.out.println("Name is"+ person.getName());
	}
}

运行application拿到ApplicationContext然后再getBean拿到person即可;
使用SpringBoot扫描注入的方式更方面,代码如下:

@Component("person")
public class Person{
	@Value("1")
	private Long id;
	@Value("Jack")
	private String name;
	...
}

这里使用了@Component配置了此类被扫描,然后@Value注入了每个属性的值;当application启动的时候,就会自动初始化加入IOC容器,所以效果与上面的一样;
@SpringBootApplication注解已经有了@ComponentScan ,所以不需要单独在启动类中加上此注解;

2.9 getBean方法的代码逻辑

  • 转换beanName
  • 从缓存中加载实例
  • 实例化Bean
  • 检测parentBeanFactory
  • 初始化依赖的Bean
  • 创建Bean

3.10 Spring Bean的作用域

  • singleton: Spring的默认作用域,容器里拥有唯一的Bean实例
  • prototype:针对每个getBean请求,容器都会创建一个Bean实例
  • request: 会为每个Http请求创建一个Bean实例
  • session: 会为每个session创建一个Bean实例
  • globalSession: 会为每个全局Http Session创建一个Bean实例,该作用域仅对Portlet有效;

3.11 SpringBean的生命周期

  • 创建过程:
    在这里插入图片描述

  • 销毁过程

    • 若实现了DisposableBean接口,则会调用destroy方法
    • 若配置了destry-method属性,则会调用其配置的销毁方法;

三. AOP

3.1 关注点分离: 不同的问题交给不同的部分去解决;

  • 面向切面编程AOP正式此种技术的体现
  • 通用化功能代码的实现,对应的就是所谓的切面;
  • 业务功能代码和切面代码分开后,架构将变得高内聚低耦合;
  • 确保功能的完整性:切面最终需要被合并到业务中(Weave)

3.2 AOP的三种织入方式

  • 编译时织入:需要特殊的Java编译器,如AspectJ
  • 类加载时织入:需要特殊的Java编译器,如AspectJ和AspectWerkz
  • 运行时织入: Spring采用的方式,通过动态代理的方式,实现简单;

3.3 运行时织入的代码演示

  1. 引入相关依赖
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</group>
		<artifactId>spring-boot-starter-web</artifactId>
	<dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-aop></artifactId>
	</dependency>
</dependencies>
  1. 创建日志类:
@Aspect
@Component
public class RequestLogAspect{
	private static final Logger logger=LoggerFactory.getLogger(RequestLogAspect.class);
	@Pointcut("execution(public * com.imooc.framework.web..*.*(..))")
	public void webLog{};
	@Before("webLog()")
	public void doBefore(JoinPoint joinPoint){
		//接收到请求,记录请求内容
		ServletRequestAttributes attributes=(ServletRequestAttributes)RequestContextHolder.get...
		//记录下请求内容
		logger.info("URL:"+ request.getRqeustURL().toString());
		logger.info("IP:"+request.getRemoteAddr());
	}
	@AfterReturning(returning="ret",pointcut="webLog()")
	public void doAfterReturning(Object ret){
		//处理完请求,返回内容
		logger.info("RESPONSE:"+ret);
	}
}

@Aspect说明这是一个切面类,@AfterReturning注解表示方法执行完后的返回值;

3.4 AOP的主要名词概念

  • Aspect:通用功能的代码实现
  • Target:被织入Aspect的对象
  • Join Point:可以作为切入点的机会,所有方法都可以作为切入点
  • Pointcut:Aspect实际被应用在的Join Point,支持正则
  • Advice:类里的方法以及这个方法如何织入到目标方法的方式
  • Weaving:Aop的实现过程;

3.5 Advice的种类

  • 前置通知(Before)
    • 在连接点前面执行,前置通知不会影响连接点的执行,除非此处抛出异常。
  • 后置通知(AfterReturning)
    • 在连接点正常执行完成后执行,如果连接点抛出异常,则不会执行。
  • 异常通知(AfterThrowing)
    • 在连接点抛出异常后执行。
  • 最终通知(After)
    • 在连接点执行完成后执行,不管是正常执行完成,还是抛出异常,都会执行返回通知中的内容。
  • 环绕通知(Around):
    • 环绕通知围绕在连接点前后,比如一个方法调用的前后。这是最强大的通知类型,能在方法调用前后自定义一些操作。环绕通知还需要负责决定是继续处理join point(调用ProceedingJoinPoint的proceed方法)还是中断执行。

五种通知的执行顺序为: 前置通知→环绕通知→后置通知/异常返回通知→最终通知,可以多次执行来查看。

四. AOP的实现原理

4.1 AOP的实现:JdkProxy和Cglib

  • 由AopProxyFactory根据AdvisedSupport对象的配置来决定
  • 默认策略如果目标类是接口,则用JDKProxy来实现,否则用后者
  • JDKProxy的核心:InvocationHandler接口和Proxy类
  • Cglib:以继承的方式动态生成目标类的代理 [如果被final修饰的类无法使用Cglib,因为无法继承]

4.2 解析:

  • JDKProxy:通过Java的内部反射机制实现

  • Cglib:借助ASM实现

  • 反射机制在生成类的过程中比较高效

  • ASM在生成类之后的执行过程中比较高效;

  • 代理模式: 接口+真实实现类+代理类

4.3 Spring里的代理模式的实现

  • 真实实现类的逻辑包含在了getBean方法里
  • getBean方法返回的实际上是Proxy的实例
  • Proxy实例是Spring采用JDK Proxy或 CGLIB动态生成的;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暗余

码字来之不易,您的鼓励我的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值