spring是怎么实现aop的
-
Spring实现AOP主要依靠动态代理和切面编程的概念。具体来说,Spring使用了两种主要的AOP实现方式:基于JDK动态代理和基于CGLIB动态代理。下面将详细介绍这两种实现方式。
-
基于JDK动态代理的AOP:
JDK动态代理是通过Java.lang.reflect包中的Proxy类和InvocationHandler接口实现的。Spring使用这种方式基于接口生成代理类来实现AOP。
首先,定义切面类,实现InvocationHandler接口,该接口中有一个invoke方法,在该方法中可以通过反射机制来执行目标方法前后的逻辑;
其次,定义目标类接口,并实现该接口的目标类;
最后,通过Proxy类的newProxyInstance方法生成代理类,并将切面类与目标类关联起来。在代理类中,通过调用切面类的invoke方法,实现AOP功能。 -
基于CGLIB动态代理的AOP:
CGLIB(Code Generation Library)是一个基于字节码生成的第三方类库,Spring使用CGLIB动态代理来实现对类的代理。与JDK动态代理不同的是,CGLIB动态代理不需要目标类实现接口。
首先,定义切面类,其中包含切面方法;
其次,定义目标类,并在其中添加被切面的方法;
最后,通过CglibProxy类的Enhancer来实现代理类的生成,并在生成的代理类中调用切面类的切面方法。
总结:
Spring使用JDK动态代理和CGLIB动态代理来实现AOP。JDK动态代理适用于接口代理,而CGLIB动态代理适用于类代理。通过继承或组合目标类和切面类,实现对目标类的增强。这样,当目标类中的方法被调用时,AOP会在方法前后插入切面方法,并实现一些横切关注点的功能,如日志记录、事务管理等。1年前 -
-
在Spring中,AOP(面向切面编程)是通过代理模式实现的。具体来说,Spring AOP使用了动态代理技术,在运行时动态地创建代理对象,从而实现了AOP的功能。
以下是Spring AOP实现的几个关键步骤:
-
定义切点(Pointcut):切点指定了在程序中哪些地方应用切面逻辑。切点通常是通过表达式或者注解来定义的。Spring AOP支持多种类型的切点表达式,包括基于正则表达式的AspectJ风格和基于注解的切点定义。
-
定义通知(Advice):通知是AOP中的具体逻辑,它定义了在切点上执行的操作。Spring AOP提供了几种不同类型的通知,包括前置通知(Before Advice)、后置通知(After Advice)、返回通知(After Returning Advice)、异常通知(After Throwing Advice)和环绕通知(Around Advice)等。
-
创建代理对象:Spring AOP使用的代理模式需要依赖代理工厂来创建代理对象。代理工厂可以根据切点和通知信息来动态创建代理对象。Spring AOP提供了两种代理方式,一种是基于JDK的动态代理(针对接口代理),另一种是基于CGLIB的动态代理(针对类代理)。
-
将代理对象织入目标对象:一旦创建了代理对象,就需要将其织入到原始的目标对象中。Spring提供了几种不同的方式来完成代理对象与目标对象的织入,包括编程式和声明式的方式。编程式的方式通过编码直接将代理对象与目标对象关联;而声明式的方式则通过配置文件或注解来指定代理对象和目标对象的关联。
-
实施AOP逻辑:一旦代理对象与目标对象成功关联,AOP逻辑就可以在程序运行过程中起作用了。当程序执行到切点处时,将自动触发相应的通知逻辑,从而实现AOP的功能。
综上所述,Spring AOP通过动态代理技术实现AOP的功能。它通过切点和通知的定义,创建代理对象,并将其织入到目标对象中,从而在运行时动态地将AOP逻辑应用到程序中。这种方式使得开发者能够更加灵活地实现横切关注点的功能。
1年前 -
-
Spring框架通过动态代理实现了AOP(面向切面编程)的功能。在Spring中,主要通过两种方式实现AOP:基于JDK的动态代理和基于CGLib的动态代理。
- 基于JDK的动态代理:
基于JDK的动态代理主要依赖于Java的反射机制,通过接口的方式实现代理,代理类和目标类都实现相同的接口。Spring提供了JdkDynamicAopProxy作为JDK动态代理的实现类。
具体实现步骤如下:
- 定义切面类:切面类是一个普通的Java类,使用@Autowired注解自动注入目标类的实例,使用@Aspect注解标识为切面类,同时使用@Pointcut定义切点。
@Aspect @Component public class MyAspect { @Autowired private TargetClass targetClass; @Pointcut("execution(* com.example.TargetClass.*(..))") public void pointcut() { } // 在目标方法执行之前执行 @Before("pointcut()") public void beforeAdvice() { System.out.println("Before advice"); } }- 配置Spring AOP:在Spring配置文件中使用aop:aspectj-autoproxy标签启用AOP功能,并通过aop:config标签配置切面类。
<aop:aspectj-autoproxy/> <aop:config> <aop:aspect ref="myAspect"> <aop:pointcut expression="execution(* com.example.TargetClass.*(..))" id="pointcut" /> <aop:before method="beforeAdvice" pointcut-ref="pointcut" /> </aop:aspect> </aop:config>- 获取代理对象:通过Spring的ApplicationContext容器获取目标类的代理对象。
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); TargetClass proxy = (TargetClass) context.getBean("targetClass");通过以上步骤,就可以实现基于JDK的动态代理。
- 基于CGLib的动态代理:
基于CGLib的动态代理主要依赖于CGLib库,通过继承的方式实现代理,代理类是目标类的子类。Spring提供了CglibAopProxy作为CGLib动态代理的实现类。
具体实现步骤如下:
- 定义切面类:同样需要使用@Autowired注解自动注入目标类的实例,使用@Aspect注解标识为切面类,同时使用@Pointcut定义切点。
@Aspect @Component public class MyAspect { @Autowired private TargetClass targetClass; @Pointcut("execution(* com.example.TargetClass.*(..))") public void pointcut() { } @Before("pointcut()") public void beforeAdvice() { System.out.println("Before advice"); } }- 配置Spring AOP:在Spring配置文件中使用aop:aspectj-autoproxy标签启用AOP功能,并通过aop:config标签配置切面类。
<aop:aspectj-autoproxy proxy-target-class="true"/> <aop:config> <aop:aspect ref="myAspect"> <aop:pointcut expression="execution(* com.example.TargetClass.*(..))" id="pointcut" /> <aop:before method="beforeAdvice" pointcut-ref="pointcut" /> </aop:aspect> </aop:config>注意需要设置aop:aspectj-autoproxy的proxy-target-class属性为true,表示使用CGLib动态代理。
- 获取代理对象:通过Spring的ApplicationContext容器获取目标类的代理对象。
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); TargetClass proxy = (TargetClass) context.getBean("targetClass");通过以上步骤,就可以实现基于CGLib的动态代理。
总结:
Spring框架通过动态代理实现AOP的功能,通过基于JDK的动态代理和基于CGLib的动态代理来实现。基于JDK的动态代理适用于接口代理,而基于CGLib的动态代理适用于类代理。无论是哪种方式,都需要定义切面类、配置Spring AOP和获取代理对象。1年前 - 基于JDK的动态代理: