对于Spring中IOC、AOP的理解。

1、如何理解spring?

简单的来讲,就是是spring是一个轻量级的容器,实现了工厂模式的工厂类,这个类名为BeanFactory(接口),在程序中通常用他的子类ApplicationContext。,其目的是为了简化企业级开发的,实现同样的功能
Spring 的核心就是控制反转 ( IoC ) 和 依赖注入 (DI)及面向切面编程 (AOP)

2、什么是ioc?

ioc是控制反转,在有了工厂模式后,我们需要某个类的对象时,就不要去new了,我们可以直接调用工程中的方法就行了,我们可以不去知道这个类的获取方式,只需要提供一个接收的方式,大大提高了开发的效率。
个人理解:IOC的思想原则,就好比是可以有一个贩卖很多物品的超市,当我们需要某个产品的时候,就直接去超市购买,我们不需要了解这个产品的制作过程,也不需要去制作这个产品,就能拿到并使用它。

DI(依赖式注入) 也是IOC的重要实现,一个对象的创建往往会涉及到其他对象的创建,这就叫做依赖,我们IOC既然提提供了对象的创建,那么这个依赖关系也必须要有ioc容器负责的方式注入,这种方式就是DI,我们通过依赖关系,写入到配置文件中,然后在创建有依赖关系的对象时,由IOC容器注入依赖的对象。举个例子,我们在创建A对象时,检查到其有依赖关系,IOC容器就把A依赖的对象B创建后,注入到A中(组装,其原理是反射机制),然后把A对象返回给对象的请求者,从而完成工作。
同样DI我们也可以这样理解:我们炒菜需要用到油,但是这个油需要用瓶子装,油和瓶子就是一个依赖关系,但是我们买油,这个制作油的工厂,会自己去制作这个瓶子(也就是依赖式注入)。


除了xml的方式配置bean外,我们还可以通过注解的方式去配置,相对于xml的方式更加优雅,和MVC的组建化开发的理念十分契合。

  • 普通组件:@Component:标识一个=受springIOC容器管理的组件
  • 持久化层组件:@Respository:标识一个受springIOC容器管理的持久化层组件
  • 业务罗基层组件:@Service:标识一个受SpringIOC容器管理的业务罗基层组件
  • 表述层控制器组件:@Controller:标识一个受springIOC容器管理的表述层控制器组件

3、spring的AOP怎么理解?

概述

首先,字面意思的去理解,AOP翻译过来就是:面向切面编程。它是通过预编译方式运行期动态代理实现程序功能的统一维护的一种技术。
提到AOP呢,我们首先想到的场景就是日志,假设一个计算器,我们希望在其运行计算方法的时候加上日志记录。我们可以想到的方法就是直接写在方法内部,但是这样写有很多弊端

  • 偶合度太高,如果我们想要修改一下日志记录的内容,那么我们不得不去每一个方法中修改。
  • 可重用性差,相同的逻辑重复的书写。

这个时候我们就发现,既然有相同的逻辑,那我们是否可以这些代码抽取出来,变成一个单独的类?这个类我们就可以看成一个切面,就想下面的代码一样:

void testCompute(){
	log();//日志方法
	startmethod();
 	compute();
    endmethod();
    log();
}

理解

那什么是面向切面编程呢?
我们将其剖析成几个关键字:程序运行期间,将某段代码动态的切入到指定方法的指定位置进行运行的这种编程方式

切面的定义我们在前面说过了,这里我们再强调几点细节 ,也就是几个术语:

  1. 横切关注点,从每个方法中抽取出来的同一类非核心业务
  2. 切面(Aspect):封装横切关注点信息的类,每个关注点体现为一个通知方法。
  3. 通知(advice):切面必须要完成的各个具体工作
  4. 目标(target):被通知的对象
  5. 代理(Proxy):向目标对象应用通知之后创建的代理对象
  6. 连接点(joinpoint):横切关注点在程序代码中具体体现,对应程序执行的某个特定位置,例如某个方法调用前、后方法捕获异常后等等
  7. 切入点(pointcut):定位连接的方式,每个类的方法都会多个连接点,所以连接点是类中客观存在的事务,如果把连接点看作数据库中的记录,那么切入点就是查询条件——AOP可以通过切入点定位到特定的连接点。切点通过org.springframework.aop.Pointcut 接口进行描述,它使用类和方法作为连接点的查询条件。

以上几个术语作为理解即可

怎么理解动态性呢?其实就是动态代理
如果有小伙伴不知道jdk代理机制的,可以先去了解一下。不了解也可以
总之呢,
针对上面那个计算器日志的例子来说,如果我们将日志以动态代理手动的写出来,那么会很复杂,很费力,而且有一个缺点,动态代理依赖接口,jdk默认的动态代理,如果目标对象没有实现任何接口,是无法为他创建代理对象的
这个时候就不得不说spring的出现,真的就是程序员的春天了
我们利用spring,可以一句代码都不写就可以去创建动态代理。而且呢,它并没有强制要求目标对象必须实现接口
那我们如何去使用呢?简单分为三步

  1. 导包:
    . commons-logging-1.1.3.jar
    spring-aop-4.0.0.RELEASE.jar
    spring-beans-4.0.0.RELEASE.jar
    spring-context-4.0.0.RELEASE.jar
    spring-core-4.0.0.RELEASE.jar
    spring-expression-4.0.0.RELEASE.jar
    Spring支持面向切面编程的包是:
    spring-aspects-4.0.0.RELEASE.jar:基础版
    加强版的面向切面编程(即使目标对象没有实现任何接口也能创建动态代理)
    com.springsource.net.sf.cglib-2.2.0.jar
    com.springsource.org.aopalliance-1.0.0.jar
    com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
  2. 写配置
    1)、将目标类和切面类(封装了通知方法(也就是在目标方法执行前后执行的方法))加到ioc容器中
    2)、还应高告诉spring到底哪个是切面类–@Aspect
    3)、告诉Spring,切面类里面的每一个方法,都是什么时候运行的。
@Before("execution(public int com.atguigu.impl.MyMathCalculator.*(int, int))")
    public static void logStart(){
        System.out.println("【xxx】方法开始执行,用的参数列表【xxx】");
    }
    //想在目标方法正常执行完成之后执行
    @AfterReturning("execution(public int com.atguigu.impl.MyMathCalculator.*(int, int))")
    public static void logReturn(){
        System.out.println("【xxxx】方法正常执行完成,计算结果是:");
    }
    //想在目标方法出现异常的时候执行
    @AfterThrowing("execution(public int com.atguigu.impl.MyMathCalculator.*(int, int))")
    public static void logException() {
        System.out.println("【xxxx】方法执行出现异常了,异常信息是:;这个异常已经通知测试小组进行排查");
    }
    //想在目标方法结束的时候执行
    @After("execution(public int com.atguigu.impl.MyMathCalculator.*(int, int))")
    public static void logEnd() {
        System.out.println("【xxx】方法最终结束了");
    }
	4)、开启基于注解的AOP模式
  1. 测试
    这个时候我们只需要调用目标方法即可
Calculator bean = ioc.getBean(Calculator.class);
        bean.method(2, 1);

那是怎么获得到代理对象呢?
我们首先要知道, 从 Proxy 的静态方法 newProxyInstance() 入手,三个参数 : class[] interfaces–代理的接口 , InvocationHandler handler --通过invoke方法,以反射的形式调用目标类的方法,ClassLoader loader–类的加载器
由此生成的代理对象,也是一个新的类,它实现了代理接口中的方法。
所以当我们调用某个ponitcut指定的方法时,实际上调用的是代理类的这个方法,而代理类的实现就是通过调用,handler的invoke方法。
就像通过Jdk提供的代理模式一样,你必须实现InvocationHandler 接口 , 因为它里面的回调方法关系到切面是否执行。
但是在spring的AOP中,我们不必自己实现InvocatiionHandler ,我们只需要将切面定义出来,在一系列的配置之后,我要在这些方法(pointcut)的这些地方(before , after) 添加advice, 然后,spring就会把这些advice 添加到一个拦截器链中,就像过滤器一样,回调方法invoke()调用的时候,就会使用这个拦截器链,然后,就会遍历这个拦截器链,看我这个方法中是否第一你这个拦截器(advisor) , 然后就是一个递归调用的过程,JdkDynamicProxy invoke():

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值