Spring 入门之SpringAop与AspectJ

Spring 入门之SpringAop与AspectJ

反思:

1.什么是spring的Ioc?为什么要设计Ioc?主要是解决什么问题?

2.什么是SpringAop?为甚要这么设计?主要解决什么问题?底层原理是什么?

3.事务的隔离级别有哪些?底层是怎么实现的?

4.静态代理和动态代理有什么区别?或者说他们都有哪些规范?

反思回答:

1.SpringIOC是一种控制反转的概念,主要是将创建对和依赖注入的控制交给Spring容器,由Spring容器管理的过程。

IoC 容器可以动态地注入依赖关系,使得更换实现类变得容易。如果需要更换某个组件的实现,只需修改容器配置,而不需要修改调用方的代码。这提高了代码的灵活性和可维护性

IoC 容器负责创建和配置组件,组件的调用方只需关注如何使用。这样可以避免重复创建对象,减少了资源浪费。例如,多个 Controller 可以复用同一个 Service,多个 Service 可以复用同一个 DAO。IoC 解决对象之间的耦合问题。

2.切面就是那些公共的,重复的,通用的逻辑功能(非主业务逻辑).AOP就是将切面单拎出来开发,在目标方法调用时自动反织回去的处理称为z面向切面编程

目的:解耦合,减少代码,让开发人员专注于业务的开发

底层实现:动态代理,jdk,cglib jdk 和cglib的动态代理的区别:

jdk需要实现接口 cglib不能是final

运行时生成的代理类,jdk之际额实现接口,而cglib继承目标类。

调用方式:jdk 反射 cglib 子类调用父类的方式

性能:jdk1.8 cglib 更好,反射的优点小于子类继承父类。后面相差无几

spring 默认采用jdk动态代理,而springboot默认采用cglib动态代理。

3.事务的隔离级别分为

  • 未提交读

    允许脏读,也就是可能读取到其他会话中未提交事务修改的数据

  • 提交读

    只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)

  • 可重复读

    可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读,但是innoDB解决了幻读

  • 窜行读

    完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞

    mysql的事务隔离级别是可重复读,Oracle的隔离级别是提交读。

事务隔离级别是如何实现的

mysql5.1.3 采用的是互斥锁 --->导致并发量降低
采用的是MVCC解决方案不需要互斥锁,但是并不是所有的事务都是采用MVCC解决方案
读未提交就没有采用MVCC,读未提交是直接去读原数据,哪怕修改数据的事务还没提
交事务也会修改目标数据,所以不需要使用任何的锁技术。串行化采用表锁。
读已提交和可重复读这两种事务隔离级别采用MVCC设计模式。
MVCC如何实现:undolog.存储我们写操作的一些历史记录存储在undolog,每次修
改记录都会用一个链表连接起来。通过保存的事务id找到相关的修改的记录,这个事
务id存储在表的隐藏列当中DB_TRX_ID,DB_ROLL_PTR。
执行select语句时,会为查询的数据创建一个快照数据表(ReadView),通过快照数据
得知有无并行的其他事务也在操作同一条数据,如果有的话,就会去undolog找到事务
提交前或者提交后的数据,这样就可以不采用互斥锁以达到读已提交的事务隔离级别。
重复读,每次都会查询undolog数据,无论读多少次都是读取同一的数据。

4.静态代理:

1)代理对象在程序运行前就已经存在.
2)代理对象就是完成业务和切面的整合
3)代理对象必须与业务对象实现同一个业务接口(保证同一套业务)
4)静态代理实现中必须有业务接口

动态代理:

 1)必须有业务接口
 2)动态代理对象是在程序运行时构建的
 3)动态代理对象是完成业务和切面功能整合的

SpringAop

原生SpringAop
1.常用以下通知
  1)Before通知:在目标方法被调用前调用,涉及接口org.springframework.aop.MethodBeforeAdvice; 
  2)After通知:在目标方法被调用后调用,涉及接口为org.springframework.aop.AfterReturningAdvice; 
  3)Throws通知:目标方法抛出异常时调用,涉及接口org.springframework.aop.ThrowsAdvice; 
  4)Around通知:拦截对目标对象方法调用,涉及接口为org.aopalliance.intercept.MethodInterceptor。
2.Aop常见的术语
1)切面Aspect	
    重复的,通用的,公共的非主业务逻辑(交叉业务逻辑)称为切面.例如:日志,事务,权限等.
  2)连接点JoinPoint
    连接业务功能和切面功能的方法(目标方法).
  3)切入点Pointcut
    多个连接点构成切入点.切入点可以是一个方法,可以是一个类,可以是一个包.
  4)目标对象Target
    对谁操作,谁就是目标对象.ProductServiceImpl,BookServiceImpl等.
  5)通知Advice
    切入切面的时机是前切后切环绕切,出错切,什么时候切入.  

3.案例代码

public class LogAdvice  implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        System.out.println("\n[系统日志]"+sf.format(new Date())+"---"+method.getName()+ Arrays.toString(objects));
    }
}
<!--创建业务对象-->
    <bean id ="bookServiceTarget" class="com.dqw.service.impl.BookServiceImpl"></bean>
    <!--创建切面的对象-->
    <bean id="logAdvice" class="com.dqw.advice.LogAdvice"></bean>

    <!--绑定业务和切面-->
    <bean id="bookService" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--配置业务接口-->
        <property name="interfaces" value="com.dqw.service.BookService"></property>
        <!--配置切面-->
        <property name="interceptorNames">
            <list>
                <value>logAdvice</value>
            </list>
        </property>
        <!--织入-->
        <property name="target" ref="bookServiceTarget"></property>
    </bean>

AspectJ

1.相关概念

Aspect是一个优秀的面向切面的框架,它扩展了Java语言提供了强大的切面实现。易学易用。

2.常见通知类型

1)@Before:前置通知,在目标方法调用前切入切面功能.
2)@AfterReturning:后置通知,在目标方法调用后切入切面功能.有可能改变目标方法的返回值.
3)@Around:环绕通知,通过拦截目标方法,在目标方法前后切入切面功能.
4)@After:最终通知,不管目标方法是否正常执行,切面功能都被切入.
5)@Pointcut:给切入点表达式起别名

AspectJ切点表达式

execution(访问权限 方法返回值 方法声明(参数) 异常类型)

常用符号:

*代表任意字符
… 出现在路径中,代表当前路径及其子路径,及其路径下的所有类
出现在方法的参数中,代表任意参数

案例代码如下:
/*
* 环绕通知切面方法规范
*   1.访问权限是public
*   2.切面有返回值为目标方法返回值
*   3.切面方法自定义
*   4.切面方法有参数,参数就是目标方法本身
*   5.需要回避异常Throwable
*   6.使用@Around注解
* */
@Aspect
@Component
public class MyAspect {

    // @Around(value = "myCut()")
    // public void myAround(ProceedingJoinPoint pjp) throws Throwable {
    //     System.out.println("环绕通知前置——————————");
    //     //获取目标方法的传参
    //     Object[] args = pjp.getArgs();
    //     System.out.println("方法名:"+pjp.getSignature());
    //     System.out.println("参数:"+ Arrays.toString(args));
    //     Object proceed = pjp.proceed();
    //     System.out.println("环绕通知后置——————————");
    // }

    @Around(value = "myCut()")
    public String myAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕通知前置——————————");
        //获取目标方法的传参
        Object[] args = pjp.getArgs();
        System.out.println("方法名:"+pjp.getSignature());
        System.out.println("参数:"+ Arrays.toString(args));
        Object proceed = pjp.proceed();
        System.out.println("环绕通知后置——————————");
        return "阿狸巴拉";
    }

    /*
    * 最终通知:
    *     主要用来做善后处理
    * 规范:
    *   1.访问权限是public
    *   2.无返回值
    *   3.切面方法自定义
    *   4.切面方法无参数,如果有是JoinPoint
    *
    * */
    @After(value = "myCut()")
    public void myAfter(){
        System.out.println("最终处理");
    }

     /*
    * 后置通知切面的规范
    *   1.访问权限是public
    *   2.切面方法没有返回值
    *   3.切面方法名任意
    *   4.一般没有传参,如果有则是业务方法的返回值
    *   用AfterReturning 注解声明
    *    参数:
    *        value 切点表达式
    *        returning 设置参数名称,与切面方法的参数名要一致
    *
    * */
    @AfterReturning(value = "myCut()",returning = "obj")
    public void myAfterReturning(Object obj){
        System.out.println("后置通知!!!");
    }

    @Before(value = "myCut()")
    public void myBefore(JoinPoint jp){
        System.out.println("前置通知");
    }
    // 简化切点表达式
    @Pointcut(value = "execution(* com.dqw.s03.*.*(..))")
    public void myCut(){}

    
}
    <context:component-scan base-package="com.dqw.s02"/>
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
修改代理为cglib
   <context:component-scan base-package="com.dqw.s02"/>
    <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

对于aop必须重点关注的是通知和切点。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值