当前位置:首页>开发>正文

spring配置aop的方式有哪些 spring 的AOP实现机制有哪些

2023-06-28 19:38:51 互联网 未知 开发

 spring配置aop的方式有哪些 spring 的AOP实现机制有哪些

spring配置aop的方式有哪些

在Spring中实现AOP根据版本不同,可以有大致四种配置方式。现简单列一下。在介绍Spring的AOP配置方式前,先要注意Spring中Advisor的概念。在Spring中Advisor是Advice和Pointcut的结合,但它还不是AOP概念上的Aspect。因为在Spring中Advisor还是Spring用来生成Aspect对象的一个原型,根据配置的不同,Spring可以只对某个类生成Aspect,也可以对所有的类生成Aspect。

1. 基于xml配置文件的代理配置方式
这种方式在2.0以后很少用了,原因是配置项过多,过于繁琐。但对于理解Spring AOP还是很有帮助的
1.1 定义通知

1.2 定义切点
要定义一个切点,可以选择使用正则表达式方式声明的切点或者AspectJ方式声明的切点。对正则表达式切点,使用Perl5RegexpMethodPointcut或JdkRegexpMethodPointcut(Java
1.4以上版本,不需要Jakarta ORO的支持了);对AspectJ切点,使用AspectJExpressPointcut
1.3 定义通知者
DefaultPointcutAdvisor是Spring提供的默认通知者,它需要提供通知和切点的引用。
Spring也提供了RegexpMethodPointcutAdvisor和AspectJExpressionPointcutAdvisor来对应两种声明切点的方式,不用再单独定义切点。


1.4 定义ProxyFactoryBean




interceptorNames和proxyInterfaces都是数组属性,所以可以声明要使用的一个list,也可以让Spring自动把单个值转化为数组

上面明确定义了要对那个targetBean应用代理生成切面实例。如果不想限制targetBean,可以让Spring为所有匹配切点声明的bean生成切面实例,这样就不用一个个定义ProxyFactoryBean了,只需要定义

这是一个BeanPostProcessor,所以Spring会自动识别并在bean的声明周期使用

2 利用2.0以后使用aop标签
3 利用Annotation

3.1 利用@Aspect将一个POJO类声明为一个切面。

3.2 定义切点
@Pointcut("execution(* *.perform(..))")
public void performance(){}
通过@Pointcut定义的切点的名字就是它所注解的方法的名字,因此例子中的切点名字是
performance()。这里声明的performance()方法实际圣只是一个标记,为@Pointcut提供附加的点,并不要求有实际意义。

3.3 定义通知
对要执行切面的方法,通过@Before("performance()"),@AfterReturning
("performance()")来定义通知。注意这里提供的切点名称,是performance(),而不是performance

如果对上面的两点不是很理解,也可以省略@Pointcut,而将AspectJ表达式直接定义在@Before等通知中,将上面的两步合为一步,如@Before("execution(* *.perform(..))")

3.4 通知Spring创建代理
这实际上相当于声明了一个AnnotationAwareAspectJAutoProxyCreator,从而根据@Pointcut声明的切点来自动代理匹配的bean实例 4 在Spring中结合进AspectJ 对于超出Spring AOP支持范围的,可以采用这种方式。只需要在Spring中配置AspectJ的Class实例时让Spring能够获得AspectJ类的实例就可以了,比如

spring 的AOP实现机制有哪些

SPRING是通过动态代理来实现AOP的,SPRING内部提供了2种实现机制1.如果是有接口声明的类进行AOP,spring调用的是java.lang.reflection.Proxy类来做处理
org.springframework.aop.framework.JdkDynamicAopProxy
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
Class targetClass = this.advised.getTargetSource().getTargetClass()
logger.debug(“Creating JDK dynamic proxy”
(targetClass != null ? ” for [" targetClass.getName() "]” : “”))
}
Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised)
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)
}
org.springframework.aop.framework.ReflectiveMethodInvocationpublic Object proceed() throws Throwable { // We start with an index of -1 and increment early. if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() – 1) { return invokeJoinpoint() } Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get( this.currentInterceptorIndex) if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this) } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed() } } else { // It’s an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this) } }2.如果是没有接口声明的类呢?SPRING通过CGLIB包和内部类来实现private static class StaticUnadvisedInterceptor implements MethodInterceptor, Serializable { private final Object target public StaticUnadvisedInterceptor(Object target) {this.target = target} public Object intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy) throws Throwable { Object retVal = methodProxy.invoke(target, args)return massageReturnTypeIfNecessary(proxy, target, retVal)}} /*** Method interceptor used for static targets with no advice chain, when the* proxy is to be exposed.*/private static class StaticUnadvisedExposedInterceptor implements MethodInterceptor, Serializable { private final Object target public StaticUnadvisedExposedInterceptor(Object target) {this.target = target} public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object oldProxy = nulltry {oldProxy = AopContext.setCurrentProxy(proxy)Object retVal = methodProxy.invoke(target, args)return massageReturnTypeIfNecessary(proxy, target, retVal)}finally {AopContext.setCurrentProxy(oldProxy)}}} /*** Interceptor used to invoke a dynamic target without creating a method* invocation or evaluating an advice chain. (We know there was no advice* for this method.)*/private class DynamicUnadvisedInterceptor implements MethodInterceptor, Serializable { public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object target = advised.getTargetSource().getTarget()try {Object retVal = methodProxy.invoke(target, args)return massageReturnTypeIfNecessary(proxy, target, retVal)}finally {advised.getTargetSource().releaseTarget(target)}}} /*** Interceptor for unadvised dynamic targets when the proxy needs exposing.*/private class DynamicUnadvisedExposedInterceptor implements MethodInterceptor, Serializable { public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object oldProxy = nullObject target = advised.getTargetSource().getTarget()try {oldProxy = AopContext.setCurrentProxy(proxy)Object retVal = methodProxy.invoke(target, args)return massageReturnTypeIfNecessary(proxy, target, retVal)}finally {AopContext.setCurrentProxy(oldProxy)advised.getTargetSource().releaseTarget(target)}}} 我们自己也可以来试试
1.jdk proxy方式先来一个接口
IHelloWorld.javapackage kris.aop.test public interface IHelloWorld { public void print(String name)public void write(String sth)} 再来一个实现HelloWorld.javapackage kris.aop.test public class HelloWorld implements IHelloWorld { public void print(String name){System.out.println(“HelloWorld “ name)} public void write(String sth) {System.out.println(“write “ sth)} } 代理类DefaultInvocationHandler.javapackage kris.aop.test import java.lang.reflect.InvocationHandlerimport java.lang.reflect.Method public class DefaultInvocationHandler implements InvocationHandler { /*** 替换外部class调用的方法* obj 外部已经已经包装好InvocationHandler的实例* method 外部方法* args 方法参数*/public Object invoke(Object obj, Method method, Object[] args)throws Throwable {String s1 []={“kris”}String s2 []={“anyone”}IHelloWorld ihw=new HelloWorld()System.out.println(“start!”)method.invoke(ihw,args)method.invoke(ihw,s1)Object o=method.invoke(ihw,s2)System.out.println(“stop!”)return o}} 测试类
Test.javapackage kris.aop.test import java.lang.reflect.InvocationHandlerimport java.lang.reflect.Proxy public class Test { public static void main(String args []){Class clazz = new HelloWorld().getClass()ClassLoader cl = clazz.getClassLoader()Class classes [] = clazz.getInterfaces()InvocationHandler ih=new DefaultInvocationHandler()//用InvocationHandler给HelloWorld进行AOP包装IHelloWorld ihw=(IHelloWorld) Proxy.newProxyInstance(cl,classes,ih)ihw.print(“test”)ihw.write(“test”)}} 2.用CGLIB包实现,首先不要忘了引入那个包package kris.aop.cglib.test public class HelloWorld { public void print(String name){System.out.println(“HelloWorld “ name)} public void write(String sth) {System.out.println(“write “ sth)}public void print(){System.out.println(“HelloWorld”)}} 代理类(没用内部类,看起来清楚点)package kris.aop.cglib.test import java.lang.reflect.Method import net.sf.cglib.proxy.MethodInterceptorimport net.sf.cglib.proxy.MethodProxy public class MethodInterceptorImpl implements MethodInterceptor { public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable { System.out.println(method) proxy.invokeSuper(obj, args) return null}} 测试类 package kris.aop.cglib.test import net.sf.cglib.proxy.Enhancer public class Test { public static void main(String[] args) { Enhancer enhancer = new Enhancer() enhancer.setSuperclass(HelloWorld.class)//设置回调方法实现类enhancer.setCallback(new MethodInterceptorImpl())//实例化已经添加回调实现的HELLOWORLD实例HelloWorld my = (HelloWorld) enhancer.create() my.print()} }

spring 中的AOP是怎么实现的

1使用ProxyFactoryBean的代理
2隐式使用ProxyFactoryBean的aop代理
DefaultAdvisorAutoProxyCreator实现了BeanPostProcessor,它将自动检查advisor的pointcut是否匹配bean的方法,如果匹配会替换bean为一个proxy,并且应用其advice。
3使用注解的aop代理
xml中增加了一个,它创建了AnnotationAwareAspectJAutoProxyCreator在spring中,这个类将自动代理匹配的类的放方法。和上个例子中DefaultAdvisorAutoProxyCreator做同样的工作。
4使用aop配置文件的自动代理采用这种方法,不用加

spring aop切面织入方式有哪些

1.通知(Advice):
通知定义了切面是什么以及何时使用。描述了切面要完成的工作和何时需要执行这个工作。
2.连接点(Joinpoint):
程序能够应用通知的一 个“时机”,这些“时机”就是连接点,例如方法被调用时、异常被抛出时等等。
3.切入点(Pointcut)
通知定义了切面要发生的“故事”和时间,那么切入点就定义了“故事”发生的地点,例如某个类或方法的名称,spring中允许我们方便的用正则表达式来指定
4.切面(Aspect)
通知和切入点共同组成了切面:时间、地点和要发生的“故事”
5.引入(Introduction)
引入允许我们向现有的类添加新的方法和属性(spring提供了一个方法注入的功能)
6.目标(Target)
即被通知的对象,如果没有AOP,那么它的逻辑将要交叉别的事务逻辑,有了AOP之后它可以只关注自己要做的事(AOP让他做爱做的事)
7.代理(proxy)
应用通知的对象,详细内容参见设计模式里面的代理模式
8.织入(Weaving)
把切面应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机:
(1)编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器
(2)类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码
(3)运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理应该是使用了JDK的动态代理技术

最新文章