Spring AOP原理
2016-05-07 00:21
363 查看
一、AOP(Aspect Oriented Programming)是Spring框架的核心技术之一,要理解AOP,先理解一些基本概念。*横切关注点(Cross-cutting concerns):*在软件开发中,分布于应用中多处的相同功能,例如:日志、安全和事务管理等,它们都是贯穿在软件的各个功能模块的,但又不是各功能模块的核心功能。*切面(Aspect):*横切关注点可以被模块化成各个不同的类,这些类就叫着切面,切面主要是由通知和切点组成。*通知(Advice):*切面要完成的目标工作就叫着通知,它定义切面在“何时”要“做什么”。通知的“何时”又分为如下几种:Before:在方法被调用之前调用通知After:在方法调用之后调用通知,无论方式是否执行成功After-returning:在方法成功执行之后调用通知After-throwing:在方法抛出异常之后调用通知Around:通知包裹了方法,通知在方法调用之前和之后执行自定义的行为*连接点(JoinPoint):*应用执行过程中能够插入切面的点就叫着连接点,在Spring的AOP中主要是指一些方法。*切点(Pointcut):*切点定义了通知在“何处”被执行,它实际上可以理解为连接点的一个子集。*引入(Introduction):*引入允许我们向现有的类添加新方法和属性,在不改变现有类的情况下,让其具有新的行为和状态。*织入(Weaving):*将切面应用到目标对象来创建新的代理对象的过程就叫着织入,在目标对象的生命周期里面,有多个时间点可以织入切面,如:编译期------ 切面在目标类编译期被织入,这种方式需要特殊的编译器,如AspectJ类加载期------ 切面在目标类家在到JVM时被织入,这种方式需要特殊的类加载器(ClassLoader)运行期------ 切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代理对象。Spring AOP就是以这种方式织入切面的,使用CGLib实现二、Spring提供了4中AOP支持:1、基于代理的经典AOP2、纯POJO切面3、@AspectJ注解驱动的切面4、注入式AspectJ切面Spring的AOP都是对方法的拦截(前三种),如果AOP需求超过了简单的方法拦截,那就应该引入AspectJ,利用Spring的DI将Spring bean注入到AspectJ切面中(第四种)。由于Spring的经典AOP不怎么样,这里也就略过了,下面直接上Spring AOP中的纯POJO切面。
package lucien; public interface Performer { void perform(); }
package lucien; import org.aspectj.lang.ProceedingJoinPoint; public class Audience { public void takeSeats() { System.out.println("观众入座"); } public void turnOffCellphones() { System.out.println("观众关闭手机"); } public void applaud() { System.out.println("观众鼓掌"); } public void demandRefund() { System.out.println("观众要求赔偿"); } public void watchPerformance(ProceedingJoinPoint joinPoint) { try { System.out.println("观众入座2"); System.out.println("观众关闭手机2"); long start = System.currentTimeMillis(); joinPoint.proceed(); long end = System.currentTimeMillis(); System.out.println("观众鼓掌2"); System.out.println("表演耗时:" + (end - start) + "秒"); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
<bean id="audience" class="lucien.Audience"/><aop:config>
<!-- 定义切面 -->
<aop:aspect ref="audience">
<!-- 定义切点 -->
<aop:pointcut id="performance" expression="execution(* lucien.Performer.perform(..))"/>
<!-- 定义通知 -->
<aop:before pointcut-ref="performance" method="takeSeats"/>
<aop:before pointcut-ref="performance" method="turnOffCellphones"/>
<aop:after-returning pointcut-ref="performance" method="applaud"/>
<aop:after-throwing pointcut-ref="performance" method="demandRefund"/>
<aop:around pointcut-ref="performance" method="watchPerformance"/>
</aop:aspect>
</aop:config>
<!-- 向通知中添加参数 -->
<bean id="magician" class="lucien.Magician"/>
<bean id="thinker" class="lucien.Volunteer"/>
<aop:config><aop:aspect ref="magician">
<aop:pointcut id="thinking" expression="execution(* lucien.Thinker.thinkOfSomething(String)) and args(thoughts)"/>
<aop:before pointcut-ref="thinking" method="interceptThoughts" arg-names="thoughts"/>
</aop:aspect>
</aop:config>
<!-- AOP给现有对象引入新功能 -->
<aop:config><aop:aspect><aop:declare-parentstypes-matching="lucien.Performer+"implement-interface="lucien.Contestant"default-impl="lucien.GraciousContestant"/></aop:aspect></aop:config>
package lucien;public interface Contestant {void receiveAward();}
package lucien;public class GraciousContestant implements Contestant {@Overridepublic void receiveAward() {// TODO Auto-generated method stubSystem.out.println("获奖");}}
package lucien;public interface Thinker {void thinkOfSomething(String thoughts);}
package lucien;public class Volunteer implements Thinker {@Overridepublic void thinkOfSomething(String thoughts) {// TODO Auto-generated method stub}}
package lucien;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test {/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubApplicationContext ctx = new ClassPathXmlApplicationContext("ConfigFile.xml");Performer performer = (Performer) ctx.getBean("poeticDuke");performer.perform();((Contestant) performer).receiveAward();Thinker thinker = (Thinker) ctx.getBean("thinker");thinker.thinkOfSomething("心事");MindReader magician = (MindReader) ctx.getBean("magician");System.out.println("心事".equals(magician.getThoughts()));}}
相关文章推荐
- Spring bean的初始化和销毁
- Spring bean的三种注入方式
- Spring bean的三种创建方式
- Spring 简介
- SpringMVC实现国际化(i18n)
- Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)
- SpringMVC访问静态文件
- 深入理解Java的接口和抽象类
- 严重: Servlet.service() for servlet [spring] in context with path [/XX] threw exception [Request
- java8一句代码搞定基本类型数组转List
- MyEclipse的WEB项目到Eclipse的迁移
- java取整和java四舍五入方法
- struts-json简单小案例
- java路径问题
- spring中classpath与classpath*区别
- Java遍历文件夹
- 关于Java中的注解
- Java 基础 -1 - 内存管理之内存分配
- Java 基础 -2 关于final
- java抽象类和接口类