2016年1月20日 星期三

AOP4-Introduction、Advice (Spring3.x 二十一)

Introduction用declare-parents的標籤實現,它的功能是有兩個interface,彼此之間沒有關係,透過這個功能可以讓它們產生父子關係,而它們兩彼此沒有耦合


※XML設定



IAOP.java和AOP.java

public interface IAOP {
    public String C();
}

@Named
public class AOP implements IAOP {
    @Override
    public String C() {
        System.out.println("無參數C");
        return "c";
    }
}



IChess.java和ChessImpl

public interface IChess {
    public void chessName();
    public String C();
}
    
@Component
public class ChessImpl implements IChess {
    @Override
    public void chessName() {
        System.out.println("象棋!");
    }
    
    @Override
    public String C() {
        System.out.println("ChessImpl");
        return "ChessImpl";
    }
}



applicationContext.xml

<context:component-scan base-package="\" />
    
<aop:config>
    <aop:aspect ref="beforeAfter">
        <aop:declare-parents types-matching="aop.AOP+" implement-interface="service.IChess" default-impl="impl.ChessImpl" />
    </aop:aspect>
</aop:config>

※aop.AOP+表示AOP的兒子,也可以用「*」等,和之前的pointcut一樣

※整行的意思是AOP的兒子可以轉成IChess


測試類

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    
// IAOP aop = (IAOP) ctx.getBean("AOP");
IChess aop = (IChess) ctx.getBean("AOP");
// IChess aop = (IChess) ctx.getBean("AOP", IAOP.class);
// IChess aop = (IChess) ctx.getBean("AOP", IChess.class);
aop.chessName();
aop.C();
// 失敗
// AOP aop = (AOP) ctx.getBean("AOP");
// IAOP aop = (IAOP) ctx.getBean("chessImpl");
    
((ClassPathXmlApplicationContext) ctx).close();

※結果:
象棋!
無參數C

※要注意方法一樣並沒有轉成設定的方法

※上面4行都是ok的,也就是AOP可以轉成自己的IAOP和設定的IChess

※這種方式只有支援interface,所以AOP轉AOP會錯

※xml的設定是AOP的兒子可以轉IChess,相反當然是不行



※Annotation設定

Annotation用的是@DeclareParents,只能寫在Field,我不太會用





※Advice

前幾篇用的before、after等方法,這是較早期用的方式

BeforeAfter.java

@Named
@Aspect
public class BeforeAfter implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) {
        System.out.println("方法=" + method);
        System.out.println("參數=" + Arrays.toString(args));
        System.out.println("物件=" + target);
    }
}

※要實作MethodBeforeAdvice的before方法


applicationContext.xml

<context:component-scan base-package="\" />
    
<aop:config>
    <aop:advisor advice-ref="beforeAfter" pointcut="execution(public void aop.AOP.A())" />
</aop:config>



測試類

    
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    
IAOP aop = (IAOP) ctx.getBean("AOP");
aop.A();
    
((ClassPathXmlApplicationContext) ctx).close();

※以前的方法每一個class都要實作MethodBeforeAdvice,所以現在很少人用了


沒有留言:

張貼留言