Spring IOC、AOP

IOC:

        Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:

        谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。

        为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

        DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

        理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

        ●谁依赖于谁:当然是应用程序依赖于IoC容器

        ●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源

        ●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象

        ●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)

    Spring依赖注入的三种方式:

  1. 使用属性的setter方法注入(例如注入属性值)。
  2. 使用构造器注入。
  3. 使用注解注入。例如:@Autowired 或 @Resource

AOP:

       AOP(Aspect-Oriented Programming,面向切面编程)是一种编程思想,并不是一种具体的实现,谈到实现一般有Filter和代理模式(也可以称之为过滤器和拦截器)两种常见的使用方式,spring中的AOP也是封装代理模式完成的,可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP利用封装、继承和多态把一切事物打造成对象结构,但是对于所有对象中都存在的一些公共行为,OOP就显得无能为力,也就是说OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。抽象和接口虽好,但对所有不相干的对象建立共同的接口或父类未免有些生硬,例如日志功能,日志代码几乎散布在所有的对象层次中,而它和散布到对象的核心功能毫无关系,对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。

AOP术语:

        连接点(Joinpoint)程序执行的某个特定位置,如某个方法调用前,调用后,方法抛出异常后,这些代码中的特定点称为连接点。简单来说,就是在哪加入你的逻辑增强
连接点表示具体要拦截的方法,上面切点是定义一个范围,而连接点是具体到某个方法

        切点(PointCut):每个程序的连接点有多个,如何定位到某个感兴趣的连接点,就需要通过切点来定位。比如,连接点--数据库的记录,切点--查询条件。切点用于来限定Spring-AOP启动的范围,通常我们采用表达式的方式来设置,所以关键词是范围

       增强(Advice): 也可以叫通知。增强是织入到目标类连接点上的一段程序代码。在Spring中,像BeforeAdvice等还带有方位信息。对照代码就是拦截器定义的相关方法,通知分为如下几种:

        1.前置通知(before):在执行业务代码前做些操作,比如获取连接对象
        2.后置通知(after):在执行业务代码后做些操作,无论是否发生异常,它都会执行,比如关闭连接对象
        3.异常通知(afterThrowing):在执行业务代码后出现异常,需要做的操作,比如回滚事务
        4.返回通知(afterReturning):在执行业务代码后无异常,会执行的操作

        目标对象(Target):需要被加强的业务对象

        织入(Weaving): 织入就是将增强添加到对目标类具体连接点上的过程。织入是一个形象的说法,具体来说,就是生成代理对象并将切面内容融入到业务流程的过程。

        代理类(Proxy):一个类被AOP织入增强后,就产生了一个代理类。

        切面(Aspect):切面由切点和增强组成,它既包括了横切逻辑的定义,也包括了连接点的定义,SpringAOP就是将切面所定义的横切逻辑织入到切面所制定的连接点中。可以简单的认为,@Aspect注解的类就是切面

AOP基础案例说明:

        已数据库操作为例,步骤如下:1.获取连接对象 2.执行SQL(核心业务代码)3.如果有异常,回滚事务,无异常则提交事务。4.关闭连接。

        其中“2”是核心业务代码,其他都是非核心业务代码。 

        

        因此,上诉数据库连接用AOP思想来表示,即:

         AOP分两类,一类可以对方法的参数进行拦截,一类是对方法进行拦截,SpringAOP属于后者,所以Spring的AOP是属于方法级的。

SpringAOP实现---基于注解的方式。

        @Aspect创建切面类。

        @Before: 标识一个前置增强方法,相当于BeforeAdvice的功能.
        @After: final增强,不管是抛出异常或者正常退出都会执行.
        @AfterReturning: 后置增强,似于AfterReturningAdvice, 方法正常退出时执行.
        @AfterThrowing: 异常抛出增强,相当于ThrowsAdvice.
        @Around: 环绕增强,相当于MethodInterceptor.
        execution:用于匹配方法执行的连接点;

过滤器和拦截器

过滤器(Filter):

    通过实现javax.servlet.Filter接口,来实现一个自定义的过滤器。

init()方法:Filter的创建和销毁由WEB服务器负责。 web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作,filter对象只会创建一次,init方法也只会执行一次。通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。

    destory()方法:Filter对象创建后会驻留在内存,当web应用移除或服务器停止时调用destroy()方法进行销毁。在Web容器卸载 Filter 对象之前被调用。destroy()方法在Filter的生命周期中仅执行一次。通过destroy()方法,可以释放过滤器占用的资源。

    doFilter()方法:拦截的请求会进入到该方法,当对拦截的请求进行预处理(上图只是进行的打印)后,需要放行该请求,直接调用chain.doFilter(request, response);若不放过该请求,直接放回return;在返回之前,对结果也可以进行预处理,处理逻辑跟在chain.doFilter(request, response)后即可。

过滤器配置:

    方式1:@WebFilter 用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器。该注解具有下表给出的一些常用属性 ( 以下所有属性均为可选属性,但是 value、urlPatterns、servletNames 三者必需至少包含一个,且 value 和 urlPatterns 不能共存,如果同时指定,通常忽略 value 的取值 )

多个filter的话,通过@Order(x)注解来区分优先级别,x越小优先级越高在SpringBootApplication(启动类)上使用@ServletComponentScan注解后,Servlet、Filter(过滤器)、Listener(监听器)可以直接通过@WebServlet@WebFilter@WebListener注解自动注册,无需其他代码。

方式2:通过FilterRegistrationBean进行注册。

拦截器:

       Java中常见的AOP技术有两个,分别是Filter和代理模式(也可以称为过滤器和拦截器),Filter是基于回调函数,代理模式是基于Java反射技术,代理模式又分为静态代理和动态代理,动态代理就是拦截器的简单实现。

       与过滤器一个很大的区别是在拦截器中可以注入 Spring 的 Bean,能够获取到各种需要的 Service 来处理业务逻辑,而过滤器则不行。

       拦截器一般是通过实现 HandlerInterceptor 接口或继承 HandlerInterceptor 接口的实现类来定义;另一种是通过实现 WebRequestInterceptor 接口或继承 WebRequestInterceptor 接口的实现类来定义。

preHandle()

该方法在控制器的处理请求方法前执行,其返回值表示是否中断后续操作,返回 true 表示继续向下执行,返回 false 表示中断后续操作

postHandle()

该方法在控制器的处理请求方法调用之后、解析视图之前执行,可以通过此方法对请求域中的模型和视图做进一步的修改

afterCompletion()

视图渲染结束后执行,可以通过此方法实现一些资源清理、记录日志信息等工作。

拦截器配置:

拦截器与过滤器的区别 :

1.  拦截器是基于java的反射机制的,而过滤器是基于函数回调。

2.  拦截器不依赖与servlet容器,过滤器依赖与servlet容器。

3.  拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。

4.  拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。

5.  在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

6.  拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑

      执行顺序 :过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后。个人认为过滤是一个横向的过程,首先把客户端提交的内容进行过滤(例如未登录用户不能访问内部页面的处理);过滤通过后,拦截器将检查用户提交数据的验证,做一些前期的数据处理,接着把处理后的数据发给对应的Action;Action处理完成返回后,拦截器还可以做其他过程(还没想到要做啥),再向上返回到过滤器的后续操作。

@Resource与@Autowired用法区别:

        参考文档:https://blog.csdn.net/magi1201/article/details/82590106

        spring中,@Resource和@Autowired都是做bean的注入时使用。使用过程中,有时候@Resource 和 @Autowired可以替换使用;有时,则不可以。

@Resource装配顺序
  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

相同点:

        @Resource和@Autowired都可以作为注入属性的修饰,在接口仅有单一实现类时,两个注解的修饰效果相同,可以互相替换,不影响使用。

        不同点:

        @Resource是Java自己的注解,@Resource有两个属性是比较重要的,分是name和type;Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

        @Autowired是spring的注解,是spring2.5版本引入的,Autowired只根据type进行注入,不会去匹配name。如果涉及到type无法辨别注入对象时,那需要依赖@Qualifier或@Primary注解一起来修饰。
       

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值