《Spring实战》学习笔记(三)面向切面的Spring
2017-02-05 15:04
791 查看
使用注解创建切面
定义切面
代码结构
程序清单
PS:定义切面package concert; import org.aspectj.lang.annotation.*; @Aspect public class Audience { @Pointcut("execution(** concert.Performance.perform(..))") public void performance() {} @Before("performance()") public void silenceCellPhones() { System.out.println("Silencing cell phones"); } @Before("performance()") public void takeSeats() { System.out.println("Taking seats"); } @AfterReturning("performance()") public void applause() { System.out.println("CLAP CLAP CLAP!!!"); } @AfterThrowing("performance()") public void demandRefund() { System.out.println("Demanding a refund"); } }
PS:Java配置,@EnableAspectJAutoProxy启用AspectJ自动代理
package concert; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration @EnableAspectJAutoProxy @ComponentScan public class ConcertConfig { @Bean public Audience audience() { return new Audience(); } }
PS:切点接口
package concert; public interface Performance { public void perform(); }
PS:切点接口实现
package concert; import org.springframework.stereotype.Component; @Component public class PerformanceImpl implements Performance { public void perform() { System.out.println("Singing!!!"); } }
PS:如果通过XML装配bean
<?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/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 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <context:component-scan base-package="concert"/> <aop:aspectj-autoproxy /> <bean class="concert.Audience" /> </beans>
测试
import concert.ConcertConfig; import concert.Performance; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = ConcertConfig.class) public class PerformanceTest { @Autowired private Performance performance; @Test public void perform() { performance.perform(); } }
创建环绕通知
PS:把上面的切面代码改为如下。package concert; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; @Aspect public class Audience { @Pointcut("execution(** concert.Performance.perform(..))") public void performance() {} @Around("performance()") public void watchPerformance(ProceedingJoinPoint jp) { try { System.out.println("Silencing cell phones"); System.out.println("Taking seats"); jp.proceed(); System.out.println("CLAP CLAP CLAP!!!"); } catch (Throwable e) { System.out.println("Demanding a refund"); } } }
处理通知中的参数
代码结构
程序清单
package soundsystem; import java.util.List; public class BlankDisc implements CompactDisc { private String title; private String artist; private List<String> tracks; public void setTitle(String title) { this.title = title; } public void setArtist(String artist) { this.artist = artist; } public void setTracks(List<String> tracks) { this.tracks = tracks; } public void play() { System.out.println("Playing "+title+" by "+artist); for(String track : tracks) { System.out.println("-Track: "+track); } } public void playTrack(int trackNumber) { System.out.println("Playing track"+trackNumber); } }
package soundsystem; public interface CompactDisc { public void play(); public void playTrack(int trackNumber); }
package soundsystem; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import java.util.HashMap; import java.util.Map; @Aspect public class TrackCounter { private Map<Integer, Integer> trackCounts = new HashMap<Integer, Integer>(); @Pointcut("execution(* soundsystem.CompactDisc.playTrack(int)) "+"&& args(trackNumber)") public void trackPlayed(int trackNumber) {} @Before("trackPlayed(trackNumber)") public void countTrack(int trackNumber) { int currentCount = getPlayCount(trackNumber); trackCounts.put(trackNumber, currentCount+1); } public int getPlayCount(int trackNumber) { return trackCounts.containsKey(trackNumber) ? trackCounts.get(trackNumber) : 0; } }
package soundsystem; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; import java.util.ArrayList; import java.util.List; @Configuration @EnableAspectJAutoProxy public class TrackCounterConfig { @Bean public CompactDisc sgtPeppers() { BlankDisc cd = new BlankDisc(); cd.setTitle("hello"); cd.setArtist("world"); List<String> tracks = new ArrayList<String>(); tracks.add("11111"); tracks.add("22222"); tracks.add("33333"); tracks.add("44444"); tracks.add("55555"); cd.setTracks(tracks); return cd; } @Bean public TrackCounter trackCounter() { return new TrackCounter(); } }
测试
import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.StandardOutputStreamLog; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import soundsystem.CompactDisc; import soundsystem.TrackCounter; import soundsystem.TrackCounterConfig; import static org.junit.Assert.assertEquals; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes= TrackCounterConfig.class) public class TrackCounterTest { @Rule public final StandardOutputStreamLog log = new StandardOutputStreamLog(); @Autowired private CompactDisc cd; @Autowired private TrackCounter counter; @Test public void testTrackCounter() { cd.playTrack(1); cd.playTrack(2); cd.playTrack(3); cd.playTrack(3); cd.playTrack(3); cd.playTrack(3); cd.playTrack(7); cd.playTrack(7); assertEquals(1, counter.getPlayCount(1)); assertEquals(1, counter.getPlayCount(2)); assertEquals(4, counter.getPlayCount(3)); assertEquals(0, counter.getPlayCount(4)); assertEquals(0, counter.getPlayCount(5)); assertEquals(0, counter.getPlayCount(6)); assertEquals(2, counter.getPlayCount(7)); } }
通过注解引入新功能
参考:Spring Aop 使用注解引入新功能代码结构
程序清单
PS:不需要,没有用到package concert; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; @Aspect public class Audience { @Pointcut("execution(** concert.Performance.perform(..))") public void performance() {} @Around("performance()") public void watchPerformance(ProceedingJoinPoint jp) { try { System.out.println("Silencing cell phones"); System.out.println("Taking seats"); jp.proceed(); System.out.println("CLAP CLAP CLAP!!!"); } catch (Throwable e) { System.out.println("Demanding a refund"); } } }
PS:注入EncoreableIntroducer
package concert; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration @EnableAspectJAutoProxy @ComponentScan public class ConcertConfig { @Bean public Audience audience() { return new Audience(); } @Bean public EncoreableIntroducer encoreableIntroducer() { return new EncoreableIntroducer(); } }
PS:Encoreable实现类
package concert; public class DefaultEncoreable implements Encoreable { public void performEncore() { System.out.println("performEncore!!!"); } }
PS:Encoreable接口
package concert; public interface Encoreable { public void performEncore(); }
PS:EncoreableIntroducer切面,加号表示Performance所有子类型,不是Performance本身
package concert; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.DeclareParents; @Aspect public class EncoreableIntroducer { @DeclareParents(value="concert.Performance+",defaultImpl = DefaultEncoreable.class) public static Encoreable encoreable; }
PS:Performance接口
package concert; public interface Performance { public void perform(); }
PS:Performance实现类
package concert; import org.springframework.stereotype.Component; @Component public class PerformanceImpl implements Performance { public void perform() { System.out.println("Singing!!!"); } }
测试
import concert.ConcertConfig; import concert.Encoreable; import concert.Performance; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = ConcertConfig.class) public class PerformanceTest { @Autowired private ApplicationContext context; @Test public void performEncore() { //对象performanceImpl不仅有PerformanceImpl的功能,也有DefaultEncoreable类的功能 Encoreable encoreable = (Encoreable) context.getBean("performanceImpl"); encoreable.performEncore(); } }
在XML声明切面
声明前置和后置通知
<aop:config> <aop:aspect ref="audience"> <aop:pointcut id="performance" expression="execution(** concert.Performance.perform(..))"/> <aop:before pointcut-ref="performance" method="silenceCellPhones" /> <aop:before pointcut-ref="performance" method="takeSeats" /> <aop:after-returning pointcut-ref="performance" method="applause" /> <aop:after-throwing pointcut-ref="performance" method="demandRefund" /> </aop:aspect> </aop:config>
package concert; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; public class Audience { public void silenceCellPhones() { System.out.println("Silencing cell phones"); } public void takeSeats() { System.out.println("Taking seats"); } public void applause() { System.out.println("CLAP CLAP CLAP!!!"); } public void demandRefund() { System.out.println("Demanding a refund"); } }
声明环绕通知
<aop:config> <aop:aspect ref="audience"> <aop:pointcut id="performance" expression="execution(** concert.Performance.perform(..))"/> <aop:around pointcut-ref="performance" method="watchPerformance"/> </aop:aspect> </aop:config>
package concert; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; public class Audience { public void watchPerformance(ProceedingJoinPoint jp) { try { System.out.println("Silencing cell phones"); System.out.println("Taking seats"); jp.proceed(); System.out.println("CLAP CLAP CLAP!!!"); } catch (Throwable e) { System.out.println("Demanding a refund"); } } }
为通知传递参数
package soundsystem; import java.util.HashMap; import java.util.Map; public class TrackCounter { private Map<Integer, Integer> trackCounts = new HashMap<Integer, Integer>(); public void countTrack(int trackNumber) { int currentCount = getPlayCount(trackNumber); trackCounts.put(trackNumber, currentCount+1); } public int getPlayCount(int trackNumber) { return trackCounts.containsKey(trackNumber) ? trackCounts.get(trackNumber) : 0; } }
<?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/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 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="trackCounter" class="soundsystem.TrackCounter"/> <bean id="cd" class="soundsystem.BlankDisc"> <property name="title" value="hello"/> <property name="artist" value="world"/> <property name="tracks"> <list> <value>11111</value> <value>22222</value> <value>33333</value> <value>44444</value> <value>55555</value> </list> </property> </bean> <aop:config> <aop:aspect ref="trackCounter"> <aop:pointcut id="trackPlayed" expression="execution(* soundsystem.CompactDisc.playTrack(int)) and args(trackNumber)"/> <aop:before pointcut-ref="trackPlayed" method="countTrack"/> </aop:aspect> </aop:config> </beans>
通过切面引入新的功能
<?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/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 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <context:component-scan base-package="concert"/> <aop:aspectj-autoproxy /> <bean id="audience" class="concert.Audience" /> <bean id="encorebleDelegate" class="concert.DefaultEncoreable"/> <aop:config> <aop:aspect ref="audience"> <aop:pointcut id="performance" expression="execution(** concert.Performance.perform(..))"/> <aop:around pointcut-ref="performance" method="watchPerformance"/> </aop:aspect> <aop:aspect> <aop:declare-parents types-matching="concert.Performance+" implement-interface="concert.Encoreable" delegate-ref="encorebleDelegate"/> </aop:aspect> </aop:config> </beans>
相关文章推荐
- javax.servlet.ServletException: Could not resolve view with name 'xxxxx'in servlet with name 'xxx'
- Struts2+Ueditor配置和图片上传
- spring下载dist.zip的几种方式
- Webcollector + Spring + MVC 搭建应用初探(六)(Lenskit 推荐系统实例)
- 五分钟读懂UML类图
- springmvc freemarker 之间的传参问题练习 出问题出现在配置文件上
- android studio 下使用eclipse 模式的快捷键
- java 通过jetty快速配置服务
- java 移动开发 11个常用工具
- java之二分法详解
- 谈谈Java内存管理
- Spring发送带附件邮件
- Spring在bean配置文件中定义电子邮件模板
- JAVA环境变量配置
- Spring通过Gmail SMTP服务器MailSender发送电子邮件
- java基础学习总结——常用类Interger,File,Math
- 配置java环境变量!
- Spring SimpleJdbcTemplate查询示例
- Spring JdbcTemplate batchUpdate() 实例
- 对于后台订单购物流程的API开发小结