spring aop
本文内容纲要:
-AOP使用场景
-SpringAOP底层技术
-AOP相关概念
-几种实现方式
什么是AOP
AOP(Aspect-OrientedProgramming,面向方面编程),它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
AOP使用场景
AOP用来封装横切关注点,具体可以在下面的场景中使用:
Authentication权限
Caching缓存
Contextpassing内容传递
Errorhandling错误处理
Lazyloading懒加载
Debugging调试
logging,tracing,profilingandmonitoring记录跟踪优化校准
Performanceoptimization性能优化
Persistence持久化
Resourcepooling资源池
Synchronization同步
Transactions事务
SpringAOP****底层技术
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;
}
}
AOP相关概念
方面(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