Spring中的Advisor,Advice,Pointcut,Advised

        在Spring中,相关的api提供了对某类方法的拦截,也提供了对某些类的代理,以下是本人对spring参考手册的理解,纯属一家之言。对方法的拦截通过定义配置Advisior,Advice,Pointcut而实现;通过Advised接口实现代理类的生成,以下分两方面拦截者和代理类来阐述

I、拦截者

一、Spring中的Advisor,Advice,Point概述

1、Advisor:充当Advice和Pointcut的适配器,类似使用Aspect的@Aspect注解的类(前一章节所述)。一般有advice和pointcut属性。

祖先接口为org.springframework.aop.Advisor,应用中可直接使用org.springframework.aop.support.DefaultPointcutAdvisor

 

2、Advice:用于定义拦截行为,祖先接口为org.aopalliance.aop.Advice,该接口只是标识接口,应用中可直接实现BeforeAdvice ,ThrowsAdvice,MethodInterceptor ,AfterReturningAdvice ,IntroductionInterceptor 等子接口

3、Pointcut:用于定义拦截目标集合,祖先接口为org.springframework.aop.Pointcut

 

二、Spring中的Advisor,Advice,Point的应用

1、编写Advisor实现类

在此可直接使用org.springframework.aop.support.DefaultPointcutAdvisor

 

2、编写Advice实现类

public class PlayAdvice implements MethodBeforeAdvice{
 public void before(Method method, Object[] args, Object target)
   throws Throwable {
  System.out.println("my before advice");
 // method.invoke(target, args); 如果再调用这句,则目标方法会执行多一次
 }
}

 

3、编写Pointcut实现类
public class PlayPointcut implements Pointcut {
 public ClassFilter getClassFilter() {
  return new PlayClassFilter();
 }
 public MethodMatcher getMethodMatcher() {
  return new PlayMethodMatcher();
 }
}
//PlayClassFilter的定义

class PlayClassFilter implements ClassFilter {
 public boolean matches(Class clazz) {
  if(clazz.getSimpleName().equals("Play"))
   return true;
  return false;
 }
}

//PlayMethodMatcher的定义

class PlayMethodMatcher implements MethodMatcher {
 public boolean isRuntime() {
  return true;
 }
 public boolean matches(Method method, Class c) {
  if(c.getSimpleName().equals("Play")&&method.getName().contains("Service"))
   return true;
  return false;
 }
 public boolean matches(Method method, Class c, Object[] args) {
  if(c.getSimpleName().equals("Play")&&method.getName().contains("Service"))
   return true;
  return false;
 }
}

 

4、编写目标类


public class Play {

  public void playService(String what){
  System.out.println("play "+what);
 }
}

5、在配置文件中配置


<bean id="adviceBean" class="com.hss.sp.aop.PlayAdvice"/>
<bean id="pointcutBean" class="com.hss.sp.aop.PlayPointcut"/>
<bean id="playService" class="com.hss.sp.service.Play"/>
<bean
   class="org.springframework.aop.support.DefaultPointcutAdvisor">
   <property name="advice" ref="adviceBean"></property>
   <property name="pointcut" ref="pointcutBean"></property>
</bean>

 

6、测试,结果

 BeanFactory bf=new ClassPathXmlApplicationContext("applicationContext.xml");
  Play play=(Play)bf.getBean("playService");
  play.playService("pingpong");

输出:

my before advice
play pingpong

 

 

II、代理者

      在Spring中创建了AOP代理之后,你能够使用org.springframework.aop.framework.Advised接口对它们进行管理。 任何AOP代理都能够被转型为这个接口,不论它实现了哪些其它接口。这个接口包括下面的方法:

Advisor[] getAdvisors();
        
        void addAdvice(Advice advice) throws AopConfigException;
        
        void addAdvice(int pos, Advice advice) 
        throws AopConfigException;
        
        void addAdvisor(Advisor advisor) throws AopConfigException;
        
        void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
        
        int indexOf(Advisor advisor);
        
        boolean removeAdvisor(Advisor advisor) throws AopConfigException;
        
        void removeAdvisor(int index) throws AopConfigException;
        
        boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
        
    boolean isFrozen();

getAdvisors()方法将为每个已经被加入工厂的通知器,拦截器或者其它通知类型返回一个通知器。如果你曾经添加一个通知器,那么所返回的通知器将是你加入的对象。 如果你曾经加入一个拦截器或者其它通知类型,Spring将把它们包装在一个通知器里,后者使用一个永远返回true的切入点。因此如果你曾经加入一个MethodInterceptor, 返回的通知器将是一个DefaultPointcutAdvisor,它可以返回你加入的MethodInterceptor和一个匹配所有类和方法的切入点。

addAdvisor()方法可以用来添加任何通知器。通常保存切入点和通知的通知器是DefaultPointcutAdvisor,它可以用于任何通知或切入点(但不包括引入类型)。

缺省情况下,你可以加入或移除通知器或者拦截器甚至当代理已经被创建之后。唯一的限制是无法加入或者移除一个引入通知器,因为工厂中获得的已有代理不能显示接口的改变(你可以通过从工厂里获取一个新的代理来避免这个问题)。

下面是一个简单的例子,它把一个AOP代理转型为Advised接口,检查并操作它的通知:

 

Advised advised = (Advised) myObject;
            Advisor[] advisors = advised.getAdvisors();
            int oldAdvisorCount = advisors.length;
            System.out.println(oldAdvisorCount + " advisors");
            
            // Add an advice like an interceptor without a pointcut
            // Will match all proxied methods
            // Can use for interceptors, before, after returning or throws advice
            advised.addAdvice(new DebugInterceptor());
            
            // Add selective advice using a pointcut
            advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice));
            
            assertEquals("Added two advisors",
        oldAdvisorCount + 2, advised.getAdvisors().length);
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值