在上一節中,咱們經過Advice能夠對目標類進行加強,使得目標類在調用的時候能夠執行加強類中的代碼,可是,加強類適配了目標類中的全部方法。若是咱們只須要對目標類中的部分方法使用加強類,該如何操做呢?好比咱們上一節的場景:乘客乘坐火車,在上車以前須要檢票,在這一節中咱們繼續添加一項業務:旅客服務。 相關代碼:ide
public interface TakingTrain { public void takeTrain(String name) throws RestException; public void customSerive(String name); } //接口的實現 public void customSerive(String name) { System.out.println("Hi, "+name+" ,may i help you?"); }
修改咱們的測試類代碼: 添加:proxy.customSerive("LaoWang");測試
@Test public void testAdivice(){ ProxyFactory factory = new ProxyFactory(); TakingTrain trainImpl = new TakingTrainImpl(); factory.setInterfaces(trainImpl.getClass().getInterfaces()); factory.setTarget(trainImpl); factory.addAdvice(new CheckTicketAdvice()); TakingTrain proxy = (TakingTrain) factory.getProxy(); try { proxy.takeTrain("LaoWang"); proxy.customSerive("LaoWang"); } catch (RestException e) { } }
打印結果:this
please show your tickes Hi LaoWang Welcome to take the train please show your tickes Hi, LaoWang ,may i help you?
這個時候咱們發現 please show your tickes這句話打印了兩遍。也就是說CheckTicketAdvice中的方法執行了兩遍。這可不是咱們想要的結果。 而咱們如今須要的是對TakingTrain 中的 takeTrain 方法以前調用。而不是全部的方法都調用。 用什麼方法能夠實現這個功能呢?AOP!它能夠經過切面講加強類有選擇的織入到目標類的特定方法中。 換句話說,咱們須要兩個功能:code
攔截類:ClassFilter 接口
攔截方法:MethodMatcher 圖片
相關的類圖 get
具體實現(使用靜態方法匹配切面):it
1.定義切面,在切面內可進行類級別和方法級別的攔截。 注意,將切點設置到切面內:io
public class StaticMethodCheckTicketAdvisor extends StaticMethodMatcherPointcutAdvisor{ public StaticMethodCheckTicketAdvisor(Advice advice) { this.setAdvice(advice); } @Override public boolean matches(Method method, Class<?> targetClass) { return "takeTrain".equals(method.getName()); } }
2.切點保持不變:class
public class CheckTicketAdvice implements MethodBeforeAdvice{ @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("please show your tickes"); } }
3.實現類:
@Test public void testStaticMethodAdvisor(){ ProxyFactory factory = new ProxyFactory(); StaticMethodCheckTicketAdvisor advisor = new StaticMethodCheckTicketAdvisor(new CheckTicketAdvice()); TakingTrain trainImpl = new TakingTrainImpl(); factory.setInterfaces(trainImpl.getClass().getInterfaces()); factory.setTarget(trainImpl); factory.addAdvisor(advisor); TakingTrain proxy = (TakingTrain) factory.getProxy(); try { proxy.takeTrain("LaoWang"); proxy.customSerive("LaoWang"); } catch (RestException e) { } }
4.打印結果:
please show your tickes Hi LaoWang Welcome to take the train Hi, LaoWang ,may i help you?
具體實現(使用表達式匹配切面):
1.定義切面,在切面內可進行類級別和方法級別的攔截。 注意,將切點,以及表達式設置到切面內:
public class RegexpMethodCheckTicketAdvisor extends RegexpMethodPointcutAdvisor{ public RegexpMethodCheckTicketAdvisor() { super(); // TODO Auto-generated constructor stub } public RegexpMethodCheckTicketAdvisor(Advice advice) { super(advice); // TODO Auto-generated constructor stub } public RegexpMethodCheckTicketAdvisor(String pattern, Advice advice) { super(pattern, advice); // TODO Auto-generated constructor stub } public RegexpMethodCheckTicketAdvisor(String[] patterns, Advice advice) { super(patterns, advice); // TODO Auto-generated constructor stub } }
2.切點保持不變:
public class CheckTicketAdvice implements MethodBeforeAdvice{ @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("please show your tickes"); } }
3.實現類:
@Test public void testRegexpMethodAdvisor(){ ProxyFactory factory = new ProxyFactory(); RegexpMethodCheckTicketAdvisor advisor = new RegexpMethodCheckTicketAdvisor(); advisor.setPattern(".*takeTrain.*"); advisor.setAdvice(new CheckTicketAdvice()); TakingTrain trainImpl = new TakingTrainImpl(); factory.setInterfaces(trainImpl.getClass().getInterfaces()); factory.setTarget(trainImpl); factory.addAdvisor(advisor); TakingTrain proxy = (TakingTrain) factory.getProxy(); try { proxy.takeTrain("LaoWang"); proxy.customSerive("LaoWang"); } catch (RestException e) { } }
4.打印結果:
please show your tickes Hi LaoWang Welcome to take the train Hi, LaoWang ,may i help you?