spring源码解析-aop第一篇

3 篇文章 0 订阅
2 篇文章 0 订阅

引子

上一篇 spring源码解析-启动流程与循环依赖 分析了spring ioc部分的源码,这一篇则分析aop源码,但aop需要先准备面向切面编程的相关知识,否则学起来会很吃力,所以aop第一篇是先看一下spring aop用到的面向切面的相关知识,为下篇读源码做准备。

aspectJ与spring aop区别

spring核心包里引入aspectJ,而aspectJ是一个完整的aop框架,那是不是spring直接使用aspectJ来实现aop相关功能呢?

spring源码解析-aop第一篇

我们先简单了解一下aspectJ,它属于编译时增强, 有专门的编译器来生成符合java字节码规范的class文件,在编译期就生成增强类,所以运行时性能损耗小,aspectJ是一个独立的完整的aop框架,也就是说它确实可以帮spring来实现所有的aop相关功能。

但实际上spring并没有完全依赖aspectJ, spring aop属于运行时增强,有接口时用jdk动态代理,其它的使用cglib动态生成代理类,它主要针对bean来使用.aspectJ与spring aop工作在两个时期,并不属于同一类,spring也没用aspectJ来生成代理类,那它们有什么关系呢? spring为什么要引入aspectJ包呢?

aspectJ与spring aop联系

springj是有引入aspectJ包,但没有使用它的编译器相关功能,只使用注解功能,通过这样的方式去掉了对xml文件的依赖,但当切面比较多时也可以使用aspectJ。

spring aop的实现方式

spring aop支持四种切面通知方式: 前置,后置,环绕,异常

前置通知:org.springframework.aop.MethodBeforeAdvice
后置通知:org.springframework.aop.AfterReturningAdvice
环绕通知:org.aopalliance.intercept.MethodInterceptor
异常通知:org.springframework.aop.ThrowsAdvice

spring aop支持四种使用方法:

1.经典aop配置方式
2.纯POJO切面
3.@AspectJ注解
4. 使用aspectJ

先定义一个被代理的类User.java

public class User  {
    public Object get() {
        System.out.println("get.............");
        return "sssss";
    }
}
  1. 经典aop配置方式

这种方式的通知类型需要在Advice(UserAdvice)中指定,如:

//实现环绕增强
public class UserAdvice implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("before interceptor");
        Object o = invocation.proceed();
        System.out.println("after interceptor");
        return o;
    }
}

然后在xml中定义两个bean,一个
RegexpMethodPointcutAdvisor类型,一个是BeanNameAutoProxyCreator类型

第一个是advisor,定义增强类方法与被代理类方法关系,解决怎么代理问题

第二个是定义目标类,解决代理谁的问题,也可以用ProxyFactoryBean为每个接口指定代理。

<bean id="user" class="com.xxx.User"></bean>
<bean id="userAdvice" class="scom.xxx.UserAdvice"></bean>

<bean id="userAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    <!--patterns,如果有多个指定的值的话,可以使用,隔开,例如value=".*add,.*delete"-->
    <property name="patterns" value=".*get"/>
    <property name="advice" ref="userAdvice"/>
</bean>

<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="*user*"></property>
<property name="interceptorNames" value="userAdvisor"></property>
</bean>

2.pojo配置方式

通过aop:config来配置所有代理方法与被代理方法之间关系

public class UserAdvice {
    public void before() {
        System.out.println("before.......");
    }

    public void after(Object o) {
        System.out.println("after.........." + o);
    }

    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        System.out.println("around before");
        Object o =  proceedingJoinPoint.proceed();
        System.out.println("around after");
        return o;
    }

    public void afterThrowing(Throwable t) {
        System.out.println("after throwing....");
    }
}

<bean id="user" class="com.xxx.User"></bean>
<bean id="userAdvice" class="scom.xxx.UserAdvice"></bean>

<aop:config>
        <aop:pointcut id="p" expression="execution (* *.get(..))"/>
        <aop:aspect ref="userAdvice">
            <aop:before method="before" pointcut-ref="p"></aop:before>
            <!--通过设置returning来将返回值传递给通知-->
            <aop:after-returning method="after" pointcut-ref="p" returning="o"/>
            <aop:around method="around" pointcut-ref="p"/>
            <!--通过设置returning来将异常对象传递给通知-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="p" throwing="t"/>
        </aop:aspect>
    </aop:config>

3.@ASpectJ注解驱动的切面

@Aspect
@Component
public class UserIntercept {

    @AfterReturning(returning = "o", pointcut = "execution(public int com.xxx.User.get())")
    public void after(Object o) {
        System.out.println("i get map:" + o);
    }

}

4.直接使用aspectJ

这里就不展述了,下一篇根据示例分析aop源码。

关注个人微信公众号:肌肉码农,回复“好友”讨论问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值