博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring AOP API
阅读量:2493 次
发布时间:2019-05-11

本文共 7111 字,大约阅读时间需要 23 分钟。

      ( 基础概念见 )

     Spring AOP API是Spring的基础,必须要了解掌握。在这里,说三个内容:Pointcut / Advice / ProxyFactoryBean

一 Pointcut 切入点

切入点作为一个接口,有几个实现类。

实现方式:使用NameMatchMethodPointcut,根据方法名字进行匹配,含有成员变量:mappedNames,匹配的方法名集合。

<.bean id=”pointcutBean”       class=”org.springframework.aop.support.NameMatchMethodPointcut”>       
sa*

二 Advice

                  Advice源代码参照链接(

    1 Throws advice

如果连接点抛出异常,throws advice在连接点返回后调用,如果throws-advice的方法抛出异常,那么它将覆盖原有异常。

接口org.springframework.aop.ThrowsAdvice不包含任何方法,仅仅是一个声明,实现类需要实现类似下面的方法:

void afterThrowing([Mthod,args,target],ThrowableSubclass);

public class TerenceThrowsAdvice implements ThrowsAdvice {    public void afterThrowing(Exception ex) throws Throwable    {        System.out.println("TerenceThrowsAdvice afterThrowing1");    }    public void afterThrowing(Methodmethod,Object[] args,Object target,Exception ex) throws Throwable    {        System.out.println("TerenceThrowsAdvice afterThrowing2:"+method.getName()+" "+target.getClass().getName());    }}

     2 After Returning advice

        后置通知必须实现org.springframework.aop.AfterReturningAdvice接口,可以访问返回值(但是不能对其修改)、被调用的方法、方法的参数和目标。如果抛出异常,将会抛出拦截器链,替代返回值。

public class TerenceAfterReturningAdvice implements AfterReturningAdvice {     public void afterReturning(Object returnValue,Method method, Object[] arga,            Object target) throws Throwable {        System.out.println("TerenceAfterReturningAdvice:"+method.getName()+" "+            target.getClass().getName()+" "+returnValue);    }}

   3 Interception around advice

     Spring的切入点模型是的切入点可以单路的于advice重用,以针对不同的advice可以使用相同的切入点。

public class TerenceMethodInterceptor implements MethodInterceptor {    public Object invoke(MethodInvocation invocation)throws Throwable {        System.out.println("TerenceMethodInterceptor 1:"+invocation.getMethod().getName()+" " +    invocation.getStaticPart().getClass().getName()     );        Object obj=invocation.proceed();        System.out.println("TerenceMethodInterceptor 2:"+obj);        return obj;    }}

    4  Introduction advice

     Spring把引入通知作为一种特殊的拦截通知,需要IntroductionAdvisor和IntroductionInterceptor,仅适用于类,不能把任何切入点一起使用。

   5 Advisor API in Spring

     Advisor是仅包含一个切入点表达式关联的单个通知的方面,除了introductions,advisor可以用于任何通知

     Org.springframework.aop.support.DefaultPointcutAdvisor是最常用的advisor类,它可以语MethodInterceptor,BeforeAdvice或者ThrowsAdvice一起使用它可以混合在Spring同一个AOP代理的Advisor和Advice。

三 ProxyFactoryBean

      ProxyFactoryBean是Spring AOP 代理的基础核心类。

1 创建SpringAOP代理      

    创建SpringAOP代理的基创建SpringAOP本方法是用org.springframework.aop.framework.ProxyFactoryBean,通过使用该类,可以完全的控制切入点和通知(advice)以及她们的顺序。

      简单的说,就是getBean(BeanId)的时候,BeanId对应配置类是ProxyFactoryBean,但是获取的并不是该类,而是通过该类的getObject()方法创建的对象,这个方法创建的是一个AOP代理包装了一个目标对象。

      通过这种方式达到代理的目的。

  1.  使用ProxyFactoryBean或者其他IoC相关类来创建AOPdialing的最大的好处也是最重要的额好处就是通知和切入点可以有IoC来管理。
  2.  如果被代理类没有实现任何借口,则使用CGLIB代理;如果有实现接口,则使用JDK代理
  3.  但是,被代理类有没有实现接口,只要设置ProxyTargetClass为True,就可以强制使用CGLIB。
  4.  如果目标类实现了一个或者多个接口,那么创建代理的类型将一来ProxyFactoryBean的配置。

       如果ProxyFactoryBean的proxyInterfaces属性被设置为要给或者多个全限定接口名(所谓的全限定接口名是指定一个类名的时候带上包名类名,如:com.terence.aop.advice.api.TerenceBefore),此时将使用基于JDK的代理,基于JDK的代理会被创建。

        那么,该类的获取配置项里面应该加入目标类属性target和包含通知列表的拦截属性interceptorNames:

defaultAdvisor
terenceAfterReturningAdvice
terenceMethodInterceptor
terenceThrowsAdvice

      由上述配置可知,则必须首先声明目标类Bean和各个通知或拦截Bean.

sa*

       类似于上述的配置,ProxyFactoryBean的proxyInterfaces属性没有被设置,但是目标类实现了一个(或者多个)接口,那么ProxyFactoryBean将自动监测到这个目标类已经实现了至少一个接口,创建一个基于JDK的代理。

完整的配置文件spring-aop-api.xml:

sa*
defaultAdvisor
terenceAfterReturningAdvice
terenceMethodInterceptor
terenceThrowsAdvice

     如果设置了ProxyFactoryBean的proxyInterfaces属性,则可以用另外一种配置方式,上述配置文件中第2部分替换为下述配置:

com.terence.aop.api.BizLogic
terenceBeforeAdvice
terenceAfterReturningAdvice
terenceMethodInterceptor
terenceThrowsAdvice

另外一点:可以使用匿名内部bean来隐藏目标和代理之间的区别。

可以通过直接定义目标bean,将其赋值给Target。

将配置

            <property name="target">

                <ref bean="bizLogicImplTarget"/>

            </property>

替换为

            <property   name="target">

                   <bean class="com.terence.aop.api.BizLogicImpl"/>

            </property>

       CGLIB代理的工作原理是在运行时生成目标类的子类,Spring配置这个生成的子类委托方法调用原来的目标,子类是通过实现Decorator模式,织入通知。

CGLIB的代理对用户是透明的,需要注意:

        -final方法不能被通知,因为他们不能被覆盖

        -不用把CGLIB添加到classpath中,在Spring3.2中,CGLIB被重新包装并并包含在Spring核心的JAR中(即基于CGLIB的AOP就像JDK动态代理一样开箱即用)。

用*做匹配,是将匹配的所有拦截器加入通知链。

terence*

2 简化的proxy定义

使用父子bean定义,以及内部bean定义,可能会带来更加简洁的代理定义。(抽象属性标记父bean,将其定义为抽象bean,不能被实例化。)

<!-- 实现方式三 -->

<!-- 通过简化的Proxy定义 -->

 

com.terence.aop.api.BizLogic
terenceBeforeAdvice
terenceAfterReturningAdvice
terenceMethodInterceptor
terenceThrowsAdvice

3 使用ProxyFactory

 

     好处是使用SpringAOP而不必依赖于SpringIOC容器。    

ProxyFactory factory=new ProxyFactory(myBusinessInterfaceImpl);    factory.addAdvice(myBusinessInterceptor);    factory.addAdvisor(myAdvisor);    MyBusinessInterface tb=(MyBusinessInterface)factory.getProxy();

     大多数情况下最佳实践是用IOC容器创建AOP代理,     虽然可以用这种硬编码方式实现,但是Spring推荐使用配置或注解方式实现。

 

4 使用auto-proxy

Spring也允许使用“自动代理”的bean定义,它可以自动代理选定的bean,这是建立在Spring的“bean post processor”功能基础上的(在加载bean的时候就可以修改),是通过使用BeanNameAutoProxyCreator实现。

 

myInterceptor

5 使用DefaultAdvisorAutoProxyCreator

       如果声明了DefaultAdvisorAutoProxyCreator,当前IOC容器中自动应用,来到创建代理的效果,不用显示声明应用advisor的bean定义。

 

 

转载地址:http://wclrb.baihongyu.com/

你可能感兴趣的文章
Lock重入锁
查看>>
docker安装 rabbitMq
查看>>
git 常用命令 入门
查看>>
关闭selinx nginx无法使用代理
查看>>
shell 脚本部署项目
查看>>
spring cloud zuul网关上传大文件
查看>>
springboot+mybatis日志显示SQL
查看>>
工作流中文乱码问题解决
查看>>
maven打包本地依赖包
查看>>
spring boot jpa 实现拦截器
查看>>
jenkins + maven+ gitlab 自动化部署
查看>>
Pull Request流程
查看>>
Lambda 表达式
查看>>
函数式数据处理(一)--流
查看>>
java 流使用
查看>>
java 用流收集数据
查看>>
java并行流
查看>>
CompletableFuture 组合式异步编程
查看>>
mysql查询某一个字段是否包含中文字符
查看>>
Java中equals和==的区别
查看>>