首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

关于spring aop 的引见

2012-10-09 
关于spring aop 的介绍一、基础接口和类1、Person接口的源码Java代码 public interface Person {public void

关于spring aop 的介绍
一、基础接口和类

     1、Person接口的源码

Java代码
public interface Person {  
    public void info();  
    public void show(String message);  


public interface Person {
public void info();
public void show(String message);
}

     2、PersonImpl类的源码

Java代码
public class PersonImpl implements Person {  
    private String name;  
    private int age;  
      
    public void setName(String name) {  
        this.name = name;  
    }  
 
    public void setAge(int age) {  
        this.age = age;  
    }  
 
    public void info() {  
        System.out.println("\t我叫" + name + ",今年" + age + "岁。");  
    }  
 
    public void show(String message) {  
        System.out.println(message);  
    }  


public class PersonImpl implements Person {
private String name;
private int age;

public void setName(String name) {
this.name = name;
}

public void setAge(int age) {
this.age = age;
}

public void info() {
System.out.println("\t我叫" + name + ",今年" + age + "岁。");
}

public void show(String message) {
System.out.println(message);
}
}


    3、bean的配置

Xml代码
<!-- 目标对象 --> 
<bean id="personTarget" value="xxx"/> 
    <property name="age" value="xx"/> 
</bean> 

<!-- 目标对象 -->
<bean id="personTarget" value="xxx"/>
<property name="age" value="xx"/>
</bean>


二、Spring AOP支持的通知类型

     一)环绕通知(Around advice)

          实现环绕通知需要实现org.aopalliance.intercept.MethodInterceptor接口。

               1、PersonAroundAdvice类的源码

Java代码
public class PersonAroundAdvice implements MethodInterceptor {  
    public Object invoke(MethodInvocation invocation) throws Throwable {  
        System.out.println("AroundAdvice:方法调用前");  
          
        //不要忘记调用invocation的proceed方法哦  
        Object result = invocation.proceed();   
          
        System.out.println("AroundAdvice:方法调用后");  
        return result;  
    }  


public class PersonAroundAdvice implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("AroundAdvice:方法调用前");

//不要忘记调用invocation的proceed方法哦
Object result = invocation.proceed();

System.out.println("AroundAdvice:方法调用后");
return result;
}
}


               2、bean配置

Xml代码
<bean id="personAroundAdvice" value="com.cjm.aop.Person"/> 
    <property name="target" ref="personTarget"/> 
    <property name="interceptorNames"> 
        <list> 
            <value>personAroundAdvice</value> 
        </list> 
    </property> 
</bean> 

<bean id="personAroundAdvice" value="com.cjm.aop.Person"/>
<property name="target" ref="personTarget"/>
<property name="interceptorNames">
<list>
<value>personAroundAdvice</value>
</list>
</property>
</bean>


               3、测试代码

Java代码
ApplicationContext context = new FileSystemXmlApplicationContext("classpath:com/cjm/aop/beans.xml");  
Person p = (Person)context.getBean("person");  //注意这里是代理工厂Bean的ID  
p.info(); 

ApplicationContext context = new FileSystemXmlApplicationContext("classpath:com/cjm/aop/beans.xml");
Person p = (Person)context.getBean("person");  //注意这里是代理工厂Bean的ID
p.info();


     二)前置通知(Before advice)

          实现前置通知需要实现org.springframework.aop.MethodBeforeAdvice接口。

               1、PersonBeforeAdvice类的源码

Java代码
public class PersonBeforeAdvice implements MethodBeforeAdvice {  
    public void before(Method method, Object[] args, Object target) throws Throwable {  
        System.out.println("BeforeAdvice:方法调用前");  
    }  


public class PersonBeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("BeforeAdvice:方法调用前");
}
}


               2、bean配置

Xml代码
<bean id="personBeforeAdvice" value="com.cjm.aop.Person"/> 
    <property name="target" ref="personTarget"/> 
    <property name="interceptorNames"> 
        <list> 
            <value>personBeforeAdvice</value> 
        </list> 
    </property> 
</bean> 

<bean id="personBeforeAdvice" value="com.cjm.aop.Person"/>
<property name="target" ref="personTarget"/>
<property name="interceptorNames">
<list>
<value>personBeforeAdvice</value>
</list>
</property>
</bean>


     三)返回后通知(After Returning advice)

          实现返回后通知需要实现org.springframework.aop.AfterReturningAdvice接口。

               1、PersonAfterReturningAdvice类的源码

Java代码
public class PersonAfterReturningAdvice implements AfterReturningAdvice {  
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {  
        System.out.println("AfterReturningAdvice:方法调用后");  
    }  


public class PersonAfterReturningAdvice implements AfterReturningAdvice {
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("AfterReturningAdvice:方法调用后");
}
}


               2、bean配置

Xml代码
<bean id="personAfterReturningAdvice" value="com.cjm.aop.Person"/> 
    <property name="target" ref="personTarget"/> 
    <property name="interceptorNames"> 
        <list> 
            <value>personAfterReturningAdvice</value> 
        </list> 
    </property> 
</bean> 

<bean id="personAfterReturningAdvice" value="com.cjm.aop.Person"/>
<property name="target" ref="personTarget"/>
<property name="interceptorNames">
<list>
<value>personAfterReturningAdvice</value>
</list>
</property>
</bean>


               3、以上的配置中,通知对目标对象的所有方法都会起作用。如果需要过滤掉一部分方法,可以用正则表达式切入点配置器或者方法名匹配切入点配置器实现。

Xml代码
<!-- 通知与正则表达式切入点一起配置 --> 
<!-- Advisor等于切入点加通知 --> 
<!-- 方法名匹配切入点配置器:org.springframework.aop.support.NameMatchMethodPointcutAdvisor --> 
<bean id="personPointcutAdvisor" ref="personAfterReturningAdvice"/> 
    <property name="patterns"> 
        <list> 
            <value>.*info.*</value> 
        </list> 
    </property> 
</bean> 
 
<bean id="person" value="com.cjm.aop.Person"/> 
    <property name="target" ref="personTarget"/> 
    <property name="interceptorNames"> 
        <list> 
            <value>personPointcutAdvisor</value> 
        </list> 
    </property> 
</bean> 

<!-- 通知与正则表达式切入点一起配置 -->
<!-- Advisor等于切入点加通知 -->
<!-- 方法名匹配切入点配置器:org.springframework.aop.support.NameMatchMethodPointcutAdvisor -->
<bean id="personPointcutAdvisor" ref="personAfterReturningAdvice"/>
<property name="patterns">
<list>
<value>.*info.*</value>
</list>
</property>
</bean>

<bean id="person" value="com.cjm.aop.Person"/>
<property name="target" ref="personTarget"/>
<property name="interceptorNames">
<list>
<value>personPointcutAdvisor</value>
</list>
</property>
</bean>


     四)异常通知(Throws advice)

          当连接点抛出异常时,异常通知被调用。实现异常通知需要实现org.springframework.aop.ThrowsAdvice接口,该接口不包含任何方法,但在实现该接口时必须实现如下形式的方法:
                 afterThrowing([Method], [args], [target], Throwable subclass)
          可以实现一个或多个这样的方法。在这些方法中,只有第四个参数是必需的,前三个参数可选。



          1、PersonThrowsAdvice类的源码

Java代码
public class PersonThrowsAdvice implements ThrowsAdvice {  
    public void afterThrowing(FileNotFoundException ex){  
        System.out.println("ThrowsAdvice >> FileNotFoundException:" + ex.toString());  
    }  
 
    public void afterThrowing(Object[] args, Exception ex){  
        System.out.println("ThrowsAdvice >> Exception:" + ex.getMessage());  
    }  
 
    public void afterThrowing(Method method, Object[] args, Object target, Throwable ex){  
        System.out.println("ThrowsAdvice >> Throwable:" + ex.getMessage());  
    }  


public class PersonThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(FileNotFoundException ex){
System.out.println("ThrowsAdvice >> FileNotFoundException:" + ex.toString());
}

public void afterThrowing(Object[] args, Exception ex){
System.out.println("ThrowsAdvice >> Exception:" + ex.getMessage());
}

public void afterThrowing(Method method, Object[] args, Object target, Throwable ex){
System.out.println("ThrowsAdvice >> Throwable:" + ex.getMessage());
}
}


          2、bean配置

Xml代码
<bean id="personThrowsAdvice" value="com.cjm.aop.Person"/> 
    <property name="target" ref="personTarget"/> 
    <property name="interceptorNames"> 
        <list> 
            <value>personThrowsAdvice</value> 
        </list> 
    </property> 
</bean> 

<bean id="personThrowsAdvice" value="com.cjm.aop.Person"/>
<property name="target" ref="personTarget"/>
<property name="interceptorNames">
<list>
<value>personThrowsAdvice</value>
</list>
</property>
</bean>


     五)引入通知(Introduction advice)

           引入通知是一种特殊的通知,它能将新的成员变量、成员方法引入到目标类中。它不能作用于任何切入点,因为它只作用于类层次,而不是方法层次。实现引入通知需要实现IntroductionAdvisor和IntroductionInterceptor接口。

           引入通知不能调用proceed方法。Advisor必须针对每个实例,并且是有状态的。

           引入通知的效果类似于设计模式中的访问者模式(Visitor Pattern)。


1、Lockable接口的源码

Java代码
public interface Lockable {  
    void lock();  
    void unlock();  
    boolean locked();  


public interface Lockable {
void lock();
void unlock();
boolean locked();
}


           2、LockableImpl类的源码

Java代码
public class LockableImpl extends DelegatingIntroductionInterceptor implements Lockable {  
    private boolean locked;  
      
    public void lock() {  
        this.locked = true;  
    }  
 
    public void unlock() {  
        this.locked = false;  
    }  
 
    public boolean locked() {  
        return this.locked;  
    }  
 
    @Override 
    public Object invoke(MethodInvocation invocation) throws Throwable {  
        if(this.locked){  
            throw new RuntimeException("加锁,无法执行");  
        }  
          
        //这里不能调用invocation的proceed方法  
        //通常不需要改写invoke方法,直接调用父类的该方法即可  
        return super.invoke(invocation);  
    }  


public class LockableImpl extends DelegatingIntroductionInterceptor implements Lockable {
private boolean locked;

public void lock() {
this.locked = true;
}

public void unlock() {
this.locked = false;
}

public boolean locked() {
return this.locked;
}

@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if(this.locked){
throw new RuntimeException("加锁,无法执行");
}

//这里不能调用invocation的proceed方法
//通常不需要改写invoke方法,直接调用父类的该方法即可
return super.invoke(invocation);
}
}


           3、PersonIntroductionAdvice类的源码

Java代码
public class PersonIntroductionAdvice extends DefaultIntroductionAdvisor {  
    public PersonIntroductionAdvice(){  
        super(new LockableImpl(), Lockable.class);  
    }  


public class PersonIntroductionAdvice extends DefaultIntroductionAdvisor {
public PersonIntroductionAdvice(){
super(new LockableImpl(), Lockable.class);
}
}


           4、bean配置

Xml代码
<!-- Advice必须针对每个实例,所以scope要设为prototype --> 
<bean id="personIntroductionAdvice" scope="prototype"/> 
 
<bean id="person" value="com.cjm.aop.Person"/> 
    <property name="target" ref="personTarget"/> 
    <property name="interceptorNames"> 
        <list> 
            <value>personIntroductionAdvice</value> 
        </list> 
    </property> 
</bean> 

<!-- Advice必须针对每个实例,所以scope要设为prototype -->
<bean id="personIntroductionAdvice" scope="prototype"/>

<bean id="person" value="com.cjm.aop.Person"/>
<property name="target" ref="personTarget"/>
<property name="interceptorNames">
<list>
<value>personIntroductionAdvice</value>
</list>
</property>
</bean>


           5、测试代码

Java代码
ApplicationContext context = new FileSystemXmlApplicationContext("classpath:com/cjm/aop/beans.xml");  
 
//获得目标bean的代理bean  
Person p = (Person)context.getBean("person");  
 
//执行代理bean的方法,此时并未调用lock方法,可以执行  
p.info();  
 
Lockable lockable = (Lockable)p;  
lockable.lock();  
 
//目标bean已被锁定,此处将抛出异常  
p.info(); 


转自http://chenjumin.iteye.com/blog/364948

热点排行