什么是AOP
AOP(Aspect-OrientedProgramming,面向方面编程),它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
AOP用来封装横切关注点,具体可以在下面的场景中使用:
Authentication权限
Caching缓存
Contextpassing内容传递
Errorhandling错误处理
Lazyloading懒加载
Debugging调试
logging,tracing,profilingandmonitoring记录跟踪优化校准
Performanceoptimization性能优化
Persistence持久化
Resourcepooling资源池
Synchronization同步
Transactions事务
Spring提供了两种方式来生成代理对象:JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。
动态代理利用反射的原理,给对象动态的生产代理对象,在执行的方法前后来执行相关内容:
/** *动态代理类 * *@authoryanbin * */ publicclassDynamicProxyimplementsInvocationHandler{ /**需要代理的目标类*/ privateObjecttarget; /** *写法固定,aop专用:绑定委托对象并返回一个代理类 * *@paramdelegate *@return */ publicObjectbind(Objecttarget){ this.target=target; returnProxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } /** *@paramObject *target:指被代理的对象。 *@paramMethod *method:要调用的方法 *@paramObject *[]args:方法调用时所需要的参数 */ @Override publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{ Objectresult=null; //切面之前执行 System.out.println("切面之前执行"); //执行业务 result=method.invoke(target,args); //切面之后执行 System.out.println("切面之后执行"); returnresult; } }CGLIB是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强。采用的是继承的方式
/** *使用cglib动态代理 * *@authoryanbin * */ publicclassCglibProxyimplementsMethodInterceptor{ privateObjecttarget; /** *创建代理对象 * *@paramtarget *@return */ publicObjectgetInstance(Objecttarget){ this.target=target; Enhancerenhancer=newEnhancer(); enhancer.setSuperclass(this.target.getClass()); //回调方法 enhancer.setCallback(this); //创建代理对象 returnenhancer.create(); } @Override publicObjectintercept(Objectproxy,Methodmethod,Object[]args,MethodProxymethodProxy)throwsThrowable{ Objectresult=null; System.out.println("事物开始"); result=methodProxy.invokeSuper(proxy,args); System.out.println("事物结束"); returnresult; } }方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的Advisor或拦截器实现。
连接点(Joinpoint):程序执行过程中明确的点,如方法的调用或特定的异常被抛出。
通知(Advice):在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice:BeforeAdvice,AfterAdvice,ThrowAdvice和DynamicIntroductionAdvice
切入点(Pointcut):指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解,MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上
引入(Introduction):添加方法或字段到被通知的类。Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现IsModified接口,来简化缓存。Spring中要使用Introduction,可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口
目标对象(TargetObject):包含连接点的对象。也被称作被通知或被代理对象。POJO
AOP代理(AOPProxy):AOP框架创建的对象,包含通知。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
织入(Weaving):组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯JavaAOP框架一样,在运行时完成织入。
1、基于代理的AOP
2、纯简单java对象切面
3、@Aspect注解形式的
4、注入形式的Aspcet切面
面先写一下几个基本的类。
接口类:
/** *定义一个接口 *@author陈丽娜 *@version2015年5月31日上午9:16:50 */ publicinterfaceSleepable{ /** *睡觉方法 *@author陈丽娜 *@version2015年5月31日上午9:17:14 */ voidsleep(); }实现类:
/** *陈丽娜本人实现睡觉接口 *@author陈丽娜 *@version2015年5月31日下午4:51:43 */ publicclassChenLliNaimplementsSleepable{ @Override publicvoidsleep(){ //TODOAuto-generatedmethodstub System.out.println("乖,该睡觉了!"); } }增强类:
/** *定义一个睡眠的增强同时实现前置和后置 *@author陈丽娜 *@version2015年5月31日上午9:24:43 */ publicclassSleepHelperimplementsMethodBeforeAdvice,AfterReturningAdvice{ @Override publicvoidafterReturning(ObjectreturnValue,Methodmethod,Object[]args,Objecttarget)throwsThrowable{ System.out.println("睡觉前要敷面膜"); } @Override publicvoidbefore(Methodmethod,Object[]args,Objecttarget)throwsThrowable{ System.out.println("睡觉后要做美梦"); } }1**、基于代理的AOP**
<!--创建一个增强advice--> <beanid="sleepHelper"class="com.tgb.springaop.aspect.SleepHelper"/> <beanid="lina"class="com.tgb.springaop.service.impl.ChenLliNa"/> <!--定义切点匹配所有的sleep方法--> <beanid="sleepPointcut"class="org.springframework.aop.support.JdkRegexpMethodPointcut"> <propertyname="pattern"value=".*sleep"></property> </bean> <!--切面增强+切点结合--> <beanid="sleepHelperAdvisor"class="org.springframework.aop.support.DefaultPointcutAdvisor"> <propertyname="advice"ref="sleepHelper"/> <propertyname="pointcut"ref="sleepPointcut"/> </bean> <!--定义代理对象--> <beanid="linaProxy"class="org.springframework.aop.framework.ProxyFactoryBean"> <propertyname="target"ref="lina"/> <propertyname="interceptorNames"value="sleepHelperAdvisor"/> </bean>如配置文件中:
pattern属性指定了正则表达式,他匹配所有的sleep方法
使用org.springframework.aop.support.DefaultPointcutAdvisor的目的是为了使切点和增强结合起来形成一个完整的切面
最后配置完后通过org.springframework.aop.framework.ProxyFactoryBean产生一个最终的代理对象。
2**、纯简单java对象切面**
纯简单java对象切面这话怎么说呢,在我看来就是相对于第一种配置,不需要使用代理,,而是通过spring的内部机制去自动扫描,这时候我们的配置文件就该如下修改:
<!--创建一个增强advice--> <beanid="sleepHelper"class="com.tgb.springaop.aspect.SleepHelper"/> <!--目标类--> <beanid="lina"class="com.tgb.springaop.service.impl.ChenLliNa"/> <!--配置切点和通知--> <beanid="sleepAdvisor"class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <propertyname="advice"ref="sleepHelper"></property> <propertyname="pattern"value=".*sleep"/> </bean> <!--自动代理配置--> <beanclass="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>是不是相对于第一种简单了许多,不用再去配置代理了。
3**、@Aspect注解形式**
根据我们的经验也知道,注解的形式相对于配置文件是简单一些的,这时候需要在已有的方法或类上家注解:
/** *通过注解的方式添加增强 *@author陈丽娜 *@version2015年5月31日上午10:26:13 */ @Aspect @Component publicclassSleepHelper03{ /*@Pointcut("execution(*com.tgb.springaop.service.impl..*(..))")*/ @Pointcut("execution(**.sleep(..))") publicvoidsleeppoint(){} @Before("sleeppoint()") publicvoidbeforeSleep(){ System.out.println("睡觉前要敷面膜"); } @AfterReturning("sleeppoint()") publicvoidafterSleep(){ System.out.println("睡觉后要做美梦"); }配置文件中只需写:
<!--扫描包--> <context:component-scanbase-package="com.tgb"annotation-config="true"/> <!--ASPECTJ注解--> <aop:aspectj-autoproxyproxy-target-class="true"/> <!--目标类--> <beanid="lina"class="com.tgb.springaop.service.impl.ChenLliNa"/>4**、注入形式的Aspcet切面**
个人感觉这个是最简单的也是最常用的,也是最灵活的。配置文件如下:
<!--目标类--> <beanid="lina"class="com.tgb.springaop.service.impl.ChenLliNa"/> <beanid="sleepHelper"class="com.tgb.springaop.aspect.SleepHelper02"/> <aop:config> <aop:aspectref="sleepHelper"> <aop:beforemethod="beforeSleep"pointcut="execution(**.sleep(..))"/> <aop:aftermethod="afterSleep"pointcut="execution(**.sleep(..))"/> </aop:aspect> </aop:config>配置文件中提到的SleepHelper02类如下:
/** *通过注解的方式添加增强 *@author陈丽娜 *@version2015年5月31日上午10:26:13 */ publicclassSleepHelper02{ publicvoidbeforeSleep(){ System.out.println("睡觉前要敷面膜"); } publicvoidafterSleep(){ System.out.println("睡觉后要做美梦"); } }参考:http://itindex.net/detail/53556-spring-aop
本文内容总结:AOP使用场景,SpringAOP底层技术,AOP相关概念,几种实现方式,
原文链接:https://www.cnblogs.com/ityouknow/p/5329550.html