spring中IOC AOP的理解

本文详细解读了Spring框架中的IoC(控制反转)原理,如何通过容器管理对象实例,并介绍了AOP(面向切面编程)的概念,包括切面、连接点、通知类型及其在业务方法中的应用。通过实例演示了如何在代码中实现AOP,提升代码复用性和可维护性。
摘要由CSDN通过智能技术生成

IOC

spring的两个核心功能分别是IOC AOP
IOC(控制反转)包括正转和反转
正转:开发人员掌握对象的创建,属性赋值,对象从生成到销毁的全部过程
反转:把原来的开发人员管理,创建对象的权限转移给代码之外的容器实现。由容器代替开发
总的来说spring框架将对象交给容器去创建和管理,我们要使用对象时直接从容器中去取对象就可以了

                白话来讲就是相当于托管,中间过程我们不用管ioc全管完了,我们只要从容器中取出来用就行。
                好比吃饭,以前我们是自己在家做饭,做了然后再吃,现在ioc就像餐馆我们只要给了钱,中间饭怎么做的我们都不管,我们只管等人家做好了拿来吃就行了

AOP

学习java我们知道了OOP就是面向对象编程,AOP就是面向切面编程
AOP(Aspect Orient Programming):面向切面编程
Aspect:表示切面,给业务方法增加的功能,叫做切面。切面一般都是业务功能,而且切面功能一般都是可以服用的。例如:日志功能,事务功能,权限检查,参数检查,统计信息等等。

Orient:面向,对着

Programming:编程

AOP作用

1)能让切面功能复用

2)能让开发人员专注页面逻辑

3)提高开发的效率

4)能实现业务功能和其他非业务功能解耦合

5)给存在的业务方法,增加功能,不用修改原来的代码

AOP中的术语

1)Aspect:切面,给业务方法增加功能。

2)JoinPoint:连接点,连接切面的业务方法,在这个业务方法执行时,会同时执行切面的方法。

3)Pointcut:切入点,是一个或者多个连接点的集合,表示这些方法执行时,都能增加切面的功能。

表示切面执行的位置

4)target:目标对象,给那个对象增加切面的功能,这个对象就是目标对象

5)Advice:通知(增强),表示切面的执行时间。在目标方法之前执行切面,还是目标方法之后执行的切面。

AOP中重要的三个要素Aspect Pointcut Advice

这个概念的理解是:在Advice的时间,在Pointcut 的位置,执行Aspect

AOP是一个动态的思想。在程序运行期间,创建代理(ServiceProxy),使用代理方法时,增加切面的功能,这个代理对象是存在内存中的。

举个小例子:你现在有个业务方法就是商品的价格,现在有一个新的需求要求提供日志功能
如果没有AOP思想那么就会直接在该业务中直接添加一个方法,如果后期又有其他需求或者对之前的需求有改变,又得回到这个业务中去修改代码。
直接的影响就是代码的可维护性低,并且还会加业务和非业务的混在一起
AOP思想例子:

public class SomeSerivceImpl implements SomeSerivce {
    @Override
    public void dosome(String name,Integer age) {
        System.out.println("业务方法doSome,计算商品的购买金额");
    }

    @Override
    public void doOther() {
        System.out.println("业务方法doOther,消减库存的");
    }
}


/**
 * 调用ServiceProxy类方法的时候,  调用真正的目标方法
 * 调用目标方法是。增加一些新的功能。
 *
 * ServiceProxy叫做代理  代理对目标的操作
 *
 * 创建代理,可以完成对目标方法的调用,增减功能。
 * 保持目标方法内容不变
 */
public class ServiceProxy implements SomeSerivce {
    SomeSerivce target=new SomeSerivceImpl();
    @Override
    public void dosome(String name,Integer age) {
        System.out.println("日志功能记录方法的时间"+new Date());
        target.dosome("gjx",23);
        System.out.println("事务功能:提交事务");
    }

    @Override
    public void doOther() {
        System.out.println("日志功能记录方法的时间"+new Date());
        target.doOther();
        System.out.println("事务功能:提交事务");
    }
}

这样的好处能保证一开始的业务方法不改变,利于维护,同时也能让开发人员专注于业务开发
@Before:前置通知(在目标代码前运行)

  //定义方法,来表示切面的具体功能
    /**
     * 前置通知方法的定义
     * 1)方法是public
     * 2)方法是void
     * 3)方法名称自定义
     * 4)方法可以有参数,如果有是JoinPoint
     *  也可以没有
     */
    /**
     * @Before:前置通知
     *  属性:value 切入点的表达式 ,表示切面的位置,在目标方法之前先执行。
     *  在这个方法时,会同时执行切面的功能
     *  位置:在方法的上面
     *      特点:
     *      1)执行时间:在目标方法之前执行
     *      2)不会影响目标方法的执行
     *      3)不会修改目标方法的执行结果
     */
//    @Before(value="execution(public void com.gjx.serivce.impl.SomeSerivceImpl.doSome(String, Integer))")
//    public void myBefore(){
//        //切面代码
//        System.out.println("前置通知:切面的功能,在目标代码执行之前执行:"+new Date());
//        System.out.println("\r\n");
//    }
//    @Before(value="execution( void com.gjx.serivce.impl.SomeSerivceImpl.doSome(String, Integer))")
//    public void myBefore1(){
//        //切面代码
//        System.out.println("前置通知:切面的功能,在目标代码执行之前执行:"+new Date());
//        System.out.println("");
//    }
    /**
     * 切面类的通知方法可以有参数
     * JoinPoint必须是他
     *
     * JOinPoint:表示正在执行业务方法,相当于反射Method
     * 使用要求:必须是参数列表的第一个
     * 作用:获取方法执行时的信息,例如方法的名称,方法的参数集合
     */
    @Before(value="execution( * *..SomeSerivceImpl.do*(..))")
    public void myBefore2(JoinPoint jp){
        //获取方法的定义
        System.out.println("前置通知,获取目标方法的定义:"+jp.getSignature());
        System.out.println("前置通知中,获取方法的名称====="+jp.getSignature().getName());
        //获取方法执行的参数
       Object arge[]= jp.getArgs();//数组存放的是,方法中所有的参数
        for (Object obj:arge) {
            System.out.println("前置通知,获取方法的参数:"+obj);
        }
        //切面代码
        System.out.println("前置通知:切面的功能,在目标代码执行之前执行:"+new Date());
        System.out.println("");
    }

@AfterRetunring:后置通知(在目标方法后执行的)

@Aspect
public class MyAspect {
    //定义方法,来表示切面的具体功能
    /**
     * 后置通知方法的定义
     * 1)方法是public
     * 2)方法是void
     * 3)方法名称自定义
     * 4)方法有参数,推荐使用Object类型。
     *
     */
    /**
     * @AfterReturning:后置通知
     *  属性:value 切入点表达式
     *  returning 自定义的变量,表示目标方法的返回值的。
     *      自定义变量名称必须和通知方法的形参名一样
     *      位置:在方法的上面
     *  特点:1在目标方法之后,执行
     *  2.能获取到目标方法的执行结果
     *  3.不会影响目标方法的执行
     *
     *  方法的参数:
     *      Object res:表示目标方法的返回值,使用res接收doOther的调用结果。
     *      Object res=doOther();
     *      
     *      后置通知的执行顺序:
     *      Object res=SOmeServiceImpl.doOther(..);
     *      myAfterReturning(res);
     *   思考:
     *			1.doOther返回是String, Integer, Long等基本类型,在后置通知中,修改返回值,是
     *		不会影响目标方法的最后调用结果的。
     *			2.doOther返回的结果是对象类型,例如Student。
     *		在后置通知方法中,修改这个Student对象的属性值,会不会影响最后调用结果?
     *
     *
     */
    @AfterReturning(value="execution(* *..SomeSerivceImpl.doOther(..))",returning = "res")
   public void myAfterReturning(Object res){
        System.out.println("后置通知:在目标方法之后执行的。能拿到执行结果"+res);
        //Object res有什么作用
        if("abcd".equals(res)){
            System.out.println("根据返回值的不同,做不同的增强功能");
        }else if ("add".equals(res)){
            System.out.println("doOthder做了添加数据库,我做备份数据");
        }
   }

@Around:环绕通知

@Aspect
public class MyAspect {
    //定义方法,来表示切面的具体功能
    /**
     * 环绕通知方法的定义
     * 1)方法是public
     * 2)方法是必须有返回值,推荐使用Object
     * 3)方法名称自定义
     * 4)方法必须有ProceedingJoinPoint
     *
     */
    /**
     *  @Around:环绕通知
     *      属性:value 切入点表达式
     *      位置:在方法定义的上面
     *      返回值:Object表示调用目标方法希望得到的执行结果(不一定是目标方法自己的返回值)
     *      参数:ProceedingJoinPoint  相当于反射中的Method
     *          作用:执行目标方法的,等于Method.invoke()
     *     特点:
     *    1.在目标方法的前和后都能增强功能。
     *    2.控制目标方法是否执行。
     *    3.修改目标方法的执行结果。
     */
    @Around(value = "execution(* *..SomeSerivce.doFrist(..))")
   public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("执行了环绕通知的myAroud方法");
       Object methodReturn;
        //想执行目标方法    ProceedingJoinPoint,表示doFrist
        methodReturn= pjp.proceed();//method.invoke(),表示执行doFirst()方法本事
       return "HellAround,表示目标方法执行的结果";
   }

@AfterThrowing:异常通知

@After:最终通知

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值