当不能直接接触源码时,同样的不能给源码增加注解,这时可以使用xml的方式声明切面并引入新方法
CompactDisc接口
package main.java.soundsystem; public interface CompactDisc { void play(); void playTrack(Integer trackNumber); }
BlankDisc实现
package main.java.soundsystem; import java.util.List; public class BlankDisc implements CompactDisc{ private String title; private String artist; private List<String> tracks; public BlankDisc setTitle(String title) { this.title = title; return this; } public BlankDisc setArtist(String artist) { this.artist = artist; return this; } public String getTitle() { return title; } public String getArtist() { return artist; } public void setTracks(List<String> tracks) { this.tracks = tracks; } public void play() { System.out.println("Playing " + title + " by " + artist); if(tracks!=null) { for (String track : tracks) { System.out.println("-Track: " + track); } } } @Override public void playTrack(Integer trackNumber) { System.out.println("Playing "+tracks.get(trackNumber-1)); } }
TrackCounter方法(无注解)
package main.java.soundsystem; import java.util.HashMap; import java.util.Map; public class TrackCounter { private Map<Integer, Integer> trackCounts = new HashMap<Integer, Integer>(); public void trackPlayed(int trackNumber) { } public void countTrack(int trackNumber) { int currentCount = getPlayCount(trackNumber); System.out.println("Track:" + trackNumber); trackCounts.put(trackNumber, currentCount + 1); } public void PrintMap() { trackCounts.forEach((k, v) -> System.out.println("Key:" + k + ",Value:" + v)); } public int getPlayCount(int trackNumber) { return trackCounts.containsKey(trackNumber) ? trackCounts.get(trackNumber) : 0; } }
xml配置文件声明切面
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="main.java.soundsystem"/> <aop:aspectj-autoproxy/> <bean id="trackCounter|" class="main.java.soundsystem.TrackCounter"/> <bean id="blankDisc" class="main.java.soundsystem.BlankDisc"> <property name="title" value="Sgt. Pepper's Lonely Heart Club Band"/> <property name="artist" value="the Beatles"/> <property name="tracks"> <list> <value>Sgt. Pepper's Lonely Hearts Club Band</value> <value>With a Little Help from My Friends</value> <value>Lucy in the Sky with Diamonds</value> <value>Getting Better</value> <value>Fixing a Hole</value> </list> </property> </bean> <aop:config> <aop:aspect ref="trackCounter|"> <aop:pointcut id="trackPlayed" expression= "execution(* main.java.soundsystem.CompactDisc.playTrack(Integer)) and args(trackNumber)" /> <aop:before pointcut-ref="trackPlayed" method="countTrack"/> </aop:aspect> </beans>
测试:
package main.java.soundsystem;
import org.springframework.beans.factory.annotation.Autowired;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:/TrackCounterConfig.xml")
public class TrackCounterTest {
@Autowired
private CompactDisc cd;
@Autowired
private TrackCounter counter;
@Test
public void testTrackCounter(){
cd.playTrack(1);
cd.playTrack(1);
cd.playTrack(3);
cd.playTrack(4);
cd.playTrack(4);
cd.playTrack(4);
assertEquals(2,counter.getPlayCount(1));
assertEquals(1,counter.getPlayCount(3));
assertEquals(3,counter.getPlayCount(4));
}
}
测试输出:
Track:1
Playing Sgt. Pepper's Lonely Hearts Club Band
Track:1
Playing Sgt. Pepper's Lonely Hearts Club Band
Track:3
Playing Lucy in the Sky with Diamonds
Track:4
Playing Getting Better
Track:4
Playing Getting Better
Track:4
Playing Getting Better
Process finished with exit code 0
Printer接口
package main.java.soundsystem; public interface Printer { void printCover(); }
CDPrinter类实现Printer接口
package main.java.soundsystem; public class CDPrinter implements Printer { @Override public void printCover() { System.out.println("print CD cover..."+Time); } public String getTime() { return Time; } public CDPrinter setTime(String time) { Time = time; return this; } private String Time; }
xml配置中增加配置,为CompactDisc接口的类引入新的父类,在aop:config配置节中增加一个切面
其中
types-matching:要给哪个接口增加新的父类,
implement-interface:新增父类
default-impl:新增父类的默认实现
<aop:aspect> <aop:declare-parents
types-matching="main.java.soundsystem.CompactDisc"
implement-interface="main.java.soundsystem.Printer"
default-impl="main.java.soundsystem.CDPrinter"/>
</aop:aspect>
增加测试方法:
@Test public void testPrinter() { ApplicationContext context = new ClassPathXmlApplicationContext("TrackCounterConfig.xml"); CompactDisc cd=(CompactDisc)context.getBean("blankDisc"); cd.play(); System.out.println("\ncast to Printer\n"); ((Printer)cd).printCover(); }
输出:
Playing Sgt. Pepper's Lonely Heart Club Band by the Beatles -Track: Sgt. Pepper's Lonely Hearts Club Band -Track: With a Little Help from My Friends -Track: Lucy in the Sky with Diamonds -Track: Getting Better -Track: Fixing a Hole cast to Printer print CD cover...null Process finished with exit code 0