Aop是Spring重要功能核心之一,他提供了一种在应用程序中将横切关注点(切面Aspect、连接点join point、通知Advice、切点pointcut、织入Weaving)与我们的核心业务增强,通过Aop可以不修改原有代码情况下对我们的代码进行增强。
**切面(Aspect):**切面是一个模块化的单元,他封装了与横切关注点相关的行为和逻辑。切面可以包含一个或者多个通知和切点。
**连接点(Join point):**连接点是在应用程序执行过程中能够插入的切面的点,它可以是方法调用、方法执行、异常抛出等。
通知(Advice):通知定义了连接点出执行的操作,常见的通知类型有前置通知(Before)和后置通知(After)、返回通知(After Returing)、异常通知(After Throwing)、环绕通知(Aroud),他描述了横切关注点的具体行为。
切点(Pointcut): 切点定义了一组连接点的表达式。它用于匹配连接点,确定在哪些连接点上应用通知,他描述了横切关注点的位置和范围。
**织入(Weaving):**织入是将切面应用到目标对象中,创建一个代理对象的过程,织入可以在编译时、类加载时和运行时进行,Spring Aop主要采用运行时动态代理实现织入。
1.定义切面: 创建一个切面类,并在其中定义通知和切点。
2.配置切面: 在Spring配置文件中声明切面,并制定腰织入的目标对象。
**3.配置通知和切入点:**在切面中定义通知和切点,并且将他们关联起来。
**4.织入切面:**通过Spring容器将切面织入懂啊目标对象中,创建一个代理对象。
**5.执行应用程序:**使用代理对象执行程序,切面和通知将在连接处执行。
静态代理是一种在编译的时就确定了代理对象和被代理对象的关系和代理方式。代理类需要手动编写,并在代码中显示地调用代理类执行横切逻辑。
动态代理是运行时生成代理对象,无需手动编写代理类。代理对象根据接口或类的定义,动态生成逻辑代理。Java中的代理实现方式主要有2种:基于接口的动态代理和机遇类的动态代理。
JDK代理是Java动态代理的一种实现方式,他是通过Java内置的反射机制来实现的。JDK代理要求被代理的对象必须实现至少一个接口,代理类实现了呗代理的对象相同的接口,
被通过InvocationHandler接口来拦截方法调用并添加额外的逻辑。JDK代理在运行时动态生成的代理对象,无需手动编写代理类,但只能代理了接口的类。
JDK动态代理在第一次使用方法调用的时候就会生成代理类,并通过反射来创建代理对象和执行方法调用,生成代理类和使用反射是在代理对象创建过程中发生的。
生成代理类需要将接口的方法描述转换为字节码,并在运行时动态地创建类代理。这个过程中涉及到反射操作。**代理对象(代替真实对象)会直接调用代理类(代替真实类)**中的相应方法,能让反射变得无需反射。
CGLIB(Code Generation Library)代理是通过生成目标类的子类来实现,他不要求被代理接口实现的接口。CGLIB代理通过继承目标类,并重写目标类和方式来实现代理功能。它使用字节码增强技术,它可以对目标类的所有非final方法进行拦截和增强。CGLIB代理相比JDK代理,它可以代理没有实现接口的类,并且比JDK代理更快,但是生成代理的大小和加载时间可能会大。
在CGLIB中,代理类和被代理类之间是继承关系。
CGLIB的FastClass是一个用于优化反射调用的类,它提供了比原声Java啊反射更高效率的方法调用,减少了反射调用的开销,通过FlastClass直接调用目标类的方法,而无需通过反射每次都进行查找。有了FastClass可以避免反射调用的开销。
CGLIB一个代理类会对应2个FastClass,一个FalstClass是配合目标一起调用,另一个FastClass配置代理本身一起调用,每个FAstClass可以对应多个方法。并提供了快速的方法和调用能力。
CGLIB使用ASM库来生成目标类的子类字节码。通过直接生成字节码,避免了使用Java反射进行方法调用的开销。相比JDK动态代理,他不需要目标类实现接口,可以代理普通类,也可以代理接口。
当需要创建一个代理对象的时候,如果缓存存在就不会创建直接从缓存获取,如果缓存不存在就动态生成代理类,然后添加到缓存中。通过缓存代理类可以提升我们的性能。它会缓存我们的代理类(每个生成的代理类都有一个唯一的类名,然后存到缓存中,以便获取代理类的时候直接从缓存获取)和FastClass对象(每个代理类对应2个)。
对于无参方法,CGLIB在生成的代理类中直接调用目标方法,而不需要反射。在第一次调用无参方法的时候,CGLIB会使用反射获取方法信息,生成一个FastClass对象执行调用。
CGLIB仍然需要通过反射获取方法信息,并使用反射来进行方法调用,CGLIB每次调用有参方法的时,都会使用反射进行方法调用。没有特殊优化的机制,因此有参方法的调用在CGLIB中仍然设计反射操作。
**接口支持:**JDK代理要求被代理对象实现接口,而CGLIB代理可以代理没有接口的类。
**性能表示:**CGLIB代理通常比JDK代理更快,因为JDK代理是操作反射,二CGLIB代理是操作目标类的字节码。
**代理生成:**JDK代理在运行时动态代理对象,二CGLIB代理实在运行时动态生成目标类的子类。
**代理对象的类型:**JDK代理生成的代理对象类型是接口的实现类,而CGLIB代理生成的代理对象类型是目标类的子类。
如果被代理对象已经实现了接口,并且对应能要求不高可以选择JDK代理。
如果被代理对象没有实现接口,或者对性能要求比较高可以选择CGLIB代理。
Spring默认情况下,如果被代理对象实现了接口,会使用JDK代理;否则会使用CGLIB代理。
Spring oAop是spring提供的,与spring紧密相连,可以与Spring的功能无缝协调工作。
AspectJ是一个独立的、功能强大、灵活的AOP框架,可以和任意的Java 应用程序一起使用,提供更多的Aop功能和更复杂的配置选择。
常用的有前置通知、后置通知、环绕通知、返回通知、异常通知。