前一篇 spring aop探寻之Before Advice
http://hehaibo.iteye.com/admin/blogs/1836392
首先来看个错误
org.springframework.aop.framework.adapter.UnknownAdviceTypeException: Advice object [com.hhb.biap.interceptor.after.InvokeLogAterAdvice@c59ad5] is neither a supported subinterface of [org.aopalliance.aop.Advice] nor an [org.springframework.aop.Advisor] at org.springframework.aop.framework.adapter.DefaultAdvisorAdapterRegistry.getInterceptors(DefaultAdvisorAdapterRegistry.java:90) at org.springframework.aop.framework.DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(DefaultAdvisorChainFactory.java:61) at org.springframework.aop.framework.AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice(AdvisedSupport.java:465) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:190) at $Proxy13.toString(Unknown Source) at java.lang.String.valueOf(String.java:2826) at java.lang.StringBuilder.append(StringBuilder.java:115) at com.hhb.biap.interceptor.test.InvokeRecordBeforeAdviceTest.testBeforeInterceptor(InvokeRecordBeforeAdviceTest.java:30) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.test.context.junit4.SpringTestMethod.invoke(SpringTestMethod.java:160) at org.springframework.test.context.junit4.SpringMethodRoadie.runTestMethod(SpringMethodRoadie.java:233) at org.springframework.test.context.junit4.SpringMethodRoadie$RunBeforesThenTestThenAfters.run(SpringMethodRoadie.java:333) at org.springframework.test.context.junit4.SpringMethodRoadie.runWithRepetitions(SpringMethodRoadie.java:217) at org.springframework.test.context.junit4.SpringMethodRoadie.runTest(SpringMethodRoadie.java:197) at org.springframework.test.context.junit4.SpringMethodRoadie.run(SpringMethodRoadie.java:143) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:160) at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51) at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44) at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27) at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37) at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:97) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
我们看下测试代码
public void testBeforeInterceptor() { //获得容器中的bean对象 BiapAppServiceImpl biapAppService = (BiapAppServiceImpl) this.applicationContext .getBean("biapAppService"); System.out.println(biapAppService); // 创建代理工厂 ProxyFactory proxyFactory = new ProxyFactory(); // proxyFactory.setOptimize(Boolean.TRUE); // proxyFactory.setProxyTargetClass(Boolean.TRUE); proxyFactory.setInterfaces(new Class[]{BiapAppService.class}); proxyFactory.setTarget(biapAppService); proxyFactory.addAdvice(new InvokeRecordBeforeAdvice()); proxyFactory.addAdvice(new InvokeLogAterAdvice()); BiapAppService proxyBiapAppService = (BiapAppService) proxyFactory .getProxy(); // System.out.println("代理对象:"+ proxyBiapAppService); BiapApp biapApp = proxyBiapAppService.getBiapAppById("biap"); System.out.println(biapApp); }
在看下这个类的代码com.hhb.biap.interceptor.after.InvokeLogAterAdvice,我想实现的调用方法后的增强
import java.lang.reflect.Method; import org.aopalliance.aop.Advice; public class InvokeLogAterAdvice implements Advice{ public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { // TODO Auto-generated method stub } }
因为我实现是aop联盟的定义的接口,而spring对aop已经有了实现,
import org.aopalliance.aop.Advice; public interface AfterAdvice extends Advice { } public interface AfterReturningAdvice extends AfterAdvice { void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable; }
但是为什么还会出现
org.springframework.aop.framework.adapter.UnknownAdviceTypeException: Advice object [com.hhb.biap.interceptor.after.InvokeLogAterAdvice@c59ad5] is neither a supported subinterface of [org.aopalliance.aop.Advice] nor an [org.springframework.aop.Advisor]
原来是spring实现捣的鬼,因为spring默认启动注册了一个注册器,如果我们用aop的话就被这个注册器拦截到,我们来看下JdkDynamicAopProxy ,这个类我们很熟悉
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation = null; Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class targetClass = null; Object target = null; try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return (equals(args[0]) ? Boolean.TRUE : Boolean.FALSE); } if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return new Integer(hashCode()); } if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal = null; if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be <code>null</code>. Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // Get the interception chain for this method. List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } else { // We need to create a method invocation... invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. retVal = invocation.proceed(); } // Massage return value if necessary. if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }、 }
我们来看看这行代码
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
在这个AdvisedSupport 里面
public class AdvisedSupport extends ProxyConfig implements Advised { /** * Determine a list of {@link org.aopalliance.intercept.MethodInterceptor} objects * for the given method, based on this configuration. * @param method the proxied method * @param targetClass the target class * @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers) */ public List getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) { MethodCacheKey cacheKey = new MethodCacheKey(method); List cached = (List) this.methodCache.get(cacheKey); if (cached == null) { cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( this, method, targetClass); this.methodCache.put(cacheKey, cached); } return cached; } }
我们再看 这行代码
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( this, method, targetClass);
接着往下看
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable { public List getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class targetClass) { // This is somewhat tricky... we have to process introductions first, // but we need to preserve order in the ultimate list. List interceptorList = new ArrayList(config.getAdvisors().length); boolean hasIntroductions = hasMatchingIntroductions(config, targetClass); AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); Advisor[] advisors = config.getAdvisors(); for (int i = 0; i < advisors.length; i++) { Advisor advisor = advisors[i]; if (advisor instanceof PointcutAdvisor) { // Add it conditionally. PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) { //注意这行代码 MethodInterceptor[] interceptors = registry.getInterceptors(advisor); MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) { if (mm.isRuntime()) { // Creating a new object instance in the getInterceptors() method // isn't a problem as we normally cache created chains. for (int j = 0; j < interceptors.length; j++) { interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptors[j], mm)); } } else { interceptorList.addAll(Arrays.asList(interceptors)); } } } } else if (advisor instanceof IntroductionAdvisor) { IntroductionAdvisor ia = (IntroductionAdvisor) advisor; if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } else { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } return interceptorList; } /** * Determine whether the Advisors contain matching introductions. */ private static boolean hasMatchingIntroductions(Advised config, Class targetClass) { for (int i = 0; i < config.getAdvisors().length; i++) { Advisor advisor = config.getAdvisors()[i]; if (advisor instanceof IntroductionAdvisor) { IntroductionAdvisor ia = (IntroductionAdvisor) advisor; if (ia.getClassFilter().matches(targetClass)) { return true; } } } return false; } }
我们再看这寒代码
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
public abstract class GlobalAdvisorAdapterRegistry { /** * Keep track of a single instance so we can return it to classes that request it. */ private static final AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry(); /** * Return the singleton DefaultAdvisorAdapterRegistry instance. */ public static AdvisorAdapterRegistry getInstance() { return instance; } }
我们再看DefaultAdvisorAdapterRegistry类的构造函
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable { private final List adapters = new ArrayList(3); /** * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters. */ public DefaultAdvisorAdapterRegistry() { //原来注册了3个适配器 registerAdvisorAdapter(new MethodBeforeAdviceAdapter()); registerAdvisorAdapter(new AfterReturningAdviceAdapter()); registerAdvisorAdapter(new ThrowsAdviceAdapter()); } public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { if (adviceObject instanceof Advisor) { return (Advisor) adviceObject; } if (!(adviceObject instanceof Advice)) { throw new UnknownAdviceTypeException(adviceObject); } Advice advice = (Advice) adviceObject; if (advice instanceof MethodInterceptor) { // So well-known it doesn't even need an adapter. return new DefaultPointcutAdvisor(advice); } for (int i = 0; i < this.adapters.size(); i++) { // Check that it is supported. AdvisorAdapter adapter = (AdvisorAdapter) this.adapters.get(i); if (adapter.supportsAdvice(advice)) { return new DefaultPointcutAdvisor(advice); } } throw new UnknownAdviceTypeException(advice); } public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List interceptors = new ArrayList(3); Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { interceptors.add(advice); } for (int i = 0; i < this.adapters.size(); i++) { AdvisorAdapter adapter = (AdvisorAdapter) this.adapters.get(i); if (adapter.supportsAdvice(advice)) { interceptors.add(adapter.getInterceptor(advisor)); } } if (interceptors.isEmpty()) { throw new UnknownAdviceTypeException(advisor.getAdvice()); } return (MethodInterceptor[]) interceptors.toArray(new MethodInterceptor[interceptors.size()]); } public void registerAdvisorAdapter(AdvisorAdapter adapter) { this.adapters.add(adapter); } }
原来问题就在这里,spring 在DefaultAdvisorAdapterRegistry 构造函数里面注册了三个适配器
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable { public boolean supportsAdvice(Advice advice) { return (advice instanceof MethodBeforeAdvice); } public MethodInterceptor getInterceptor(Advisor advisor) { MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice(); return new MethodBeforeAdviceInterceptor(advice); } }
class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable { public boolean supportsAdvice(Advice advice) { return (advice instanceof AfterReturningAdvice); } public MethodInterceptor getInterceptor(Advisor advisor) { AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice(); return new AfterReturningAdviceInterceptor(advice); } }
class ThrowsAdviceAdapter implements AdvisorAdapter, Serializable { public boolean supportsAdvice(Advice advice) { return (advice instanceof ThrowsAdvice); } public MethodInterceptor getInterceptor(Advisor advisor) { return new ThrowsAdviceInterceptor(advisor.getAdvice()); } }
我想我们看到这个类图就清楚了。
接下来我们再看DefaultAdvisorChainFactory 类中的这行代码
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
这个返回的是
org.aopalliance.intercept.MethodInterceptor
从上面贴代码我们就可以看出 所谓的MethodBeforeAdvice,AfterReturningAdvice,ThrowsAdviceInterceptor都是MethodInterceptor的子类!
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable { private MethodBeforeAdvice advice; /** * Create a new MethodBeforeAdviceInterceptor for the given advice. * @param advice the MethodBeforeAdvice to wrap */ public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); } }
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable { private final AfterReturningAdvice advice; /** * Create a new AfterReturningAdviceInterceptor for the given advice. * @param advice the AfterReturningAdvice to wrap */ public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } public Object invoke(MethodInvocation mi) throws Throwable { Object retVal = mi.proceed(); this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); return retVal; } }
public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice { private static final String AFTER_THROWING = "afterThrowing"; private static final Log logger = LogFactory.getLog(ThrowsAdviceInterceptor.class); private final Object throwsAdvice; /** Methods on throws advice, keyed by exception class */ private final Map exceptionHandlerMap = new HashMap(); /** * Create a new ThrowsAdviceInterceptor for the given ThrowsAdvice. * @param throwsAdvice the advice object that defines the exception * handler methods (usually a {@link org.springframework.aop.ThrowsAdvice} * implementation) */ public ThrowsAdviceInterceptor(Object throwsAdvice) { Assert.notNull(throwsAdvice, "Advice must not be null"); this.throwsAdvice = throwsAdvice; Method[] methods = throwsAdvice.getClass().getMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (method.getName().equals(AFTER_THROWING) && //m.getReturnType() == null && (method.getParameterTypes().length == 1 || method.getParameterTypes().length == 4) && Throwable.class.isAssignableFrom(method.getParameterTypes()[method.getParameterTypes().length - 1]) ) { // Have an exception handler this.exceptionHandlerMap.put(method.getParameterTypes()[method.getParameterTypes().length - 1], method); if (logger.isDebugEnabled()) { logger.debug("Found exception handler method: " + method); } } } if (this.exceptionHandlerMap.isEmpty()) { throw new IllegalArgumentException( "At least one handler method must be found in class [" + throwsAdvice.getClass() + "]"); } } public int getHandlerMethodCount() { return this.exceptionHandlerMap.size(); } /** * Determine the exception handle method. Can return null if not found. * @param exception the exception thrown * @return a handler for the given exception type */ private Method getExceptionHandler(Throwable exception) { Class exceptionClass = exception.getClass(); if (logger.isTraceEnabled()) { logger.trace("Trying to find handler for exception of type [" + exceptionClass.getName() + "]"); } Method handler = (Method) this.exceptionHandlerMap.get(exceptionClass); while (handler == null && !exceptionClass.equals(Throwable.class)) { exceptionClass = exceptionClass.getSuperclass(); handler = (Method) this.exceptionHandlerMap.get(exceptionClass); } if (handler != null && logger.isDebugEnabled()) { logger.debug("Found handler for exception of type [" + exceptionClass.getName() + "]: " + handler); } return handler; } public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } catch (Throwable ex) { Method handlerMethod = getExceptionHandler(ex); if (handlerMethod != null) { invokeHandlerMethod(mi, ex, handlerMethod); } throw ex; } } private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable { Object[] handlerArgs; if (method.getParameterTypes().length == 1) { handlerArgs = new Object[] { ex }; } else { handlerArgs = new Object[] {mi.getMethod(), mi.getArguments(), mi.getThis(), ex}; } try { method.invoke(this.throwsAdvice, handlerArgs); } catch (InvocationTargetException targetEx) { throw targetEx.getTargetException(); } } }
因为我定义这个类
public class InvokeLogAterAdvice implements AfterReturningAdvice{ public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { // TODO Auto-generated method stub } }
spring的适配器都匹配不到,所有救抛出了
org.springframework.aop.framework.adapter.UnknownAdviceTypeException: Advice object [com.hhb.biap.interceptor.after.InvokeLogAterAdvice@c59ad5] is neither a supported subinterface of [org.aopalliance.aop.Advice] nor an [org.springframework.aop.Advisor]
spring真精妙~
相关推荐
Spring AOP支持五种类型的通知:前置通知(Before)、后置通知(After)、返回后通知(After Returning)、异常后通知(After Throwing)和环绕通知(Around)。 3. **切点(Pointcut)**:切点是程序执行过程中的...
Spring AOP中有五种不同类型的的通知(Advice): 1. 前置通知(Before Advice):在方法执行前执行,使用`@Before`注解。 2. 返回后通知(After Returning Advice):在方法正常返回后执行,使用`@AfterReturning`...
Spring AOP(面向切面编程)是Spring框架的重要组成部分,它提供了一种模块化和声明式的方式来处理系统中的交叉关注点问题,如日志、事务管理、安全性等。本示例将简要介绍如何在Spring应用中实现AOP,通过实际的...
Spring AOP,全称Aspect-Oriented Programming(面向切面编程),是Spring框架的重要组成部分,它为Java应用程序提供了声明式的企业级服务,如事务管理、性能监控等。在Spring AOP中,我们可以通过定义切面(Aspect...
Spring AOP(面向切面编程)是Spring框架的核心特性之一,它允许开发者在不修改源代码的情况下,通过插入切面来增强或改变程序的行为。在本教程中,我们将深入探讨Spring AOP的不同使用方法,包括定义切点、通知类型...
Spring AOP 是一种面向切面编程的技术,它允许我们在不修改源代码的情况下,对应用程序的特定部分(如方法调用)进行增强。在 Spring 中,AOP 的实现主要依赖于代理模式,有两种代理方式:JDK 动态代理和 CGLIB 动态...
Spring AOP,全称Aspect-Oriented Programming(面向切面编程),是Spring框架的一个重要模块,它通过提供声明式的方式来实现面向切面编程,从而简化了应用程序的开发和维护。在Spring AOP中,我们无需深入到每个...
spring-aop-1.1.1.jar spring-aop-1.2.6.jar spring-aop-1.2.9.jar spring-aop-2.0.2.jar spring-aop-2.0.6.jar spring-aop-2.0.7.jar spring-aop-2.0.8.jar spring-aop-2.0.jar spring-aop-2.5.1.jar spring-aop-...
3. **灵活的通知模型**:Spring AOP提供了多种类型的通知,包括around、before、after returning、after throwing等,使得开发者可以根据实际需求选择最适合的通知类型。 4. **丰富的切入点表达式语言**:Spring ...
Spring AOP(面向切面编程)是Spring框架的核心特性之一,它允许程序员在不修改源代码的情况下,通过“切面”来插入额外的业务逻辑,如日志、事务管理等。AOP的引入极大地提高了代码的可复用性和可维护性。 ### 1. ...
在这个版本中,Spring AOP支持基于注解的切面定义,比如`@Aspect`、`@Before`、`@After`等,同时也支持基于XML配置的切面定义。这个jar包使得Spring应用程序能够方便地利用AOP特性,无需引入额外的编译工具或构建...
通过以上介绍,我们可以看到Spring AOP的强大之处在于它简化了代码的组织和维护,使得横切关注点的实现更加优雅。了解并掌握这些概念,开发者可以有效地利用Spring AOP提升应用程序的可维护性和可扩展性。
Spring支持五种类型的Advice:Before、After、After Returning、After Throwing、Around。 3. **切入点(Pointcut)**:切入点是定义通知将被应用到的精确位置,通常是方法的签名。Spring使用表达式语言(如XPath)...
在Spring AOP中,切面通常由一个或多个通知(Advice)组成,通知是在特定连接点(Join Point)执行的代码片段。连接点是指程序执行过程中能够插入切面的特定位置,如方法调用、异常抛出等。 在Spring AOP中,有五种...
在软件开发中,Spring框架以其强大的功能和灵活性,已经成为Java企业级应用的首选框架之一。其中,Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的重要组成部分,它为开发者提供了在不侵入...
5. 解析 Advice:在解析 Aspect 配置时,Spring AOP 也会解析 Advice 配置,例如 `<aop:before>` 标签。在这个过程中,Spring AOP 使用 adviceParser 来解析 Advice 配置,并生成相应的 Bean 定义对象。 6. 注册 ...
Spring AOP,全称Aspect-Oriented Programming(面向切面编程),是Spring框架的重要组成部分,用于实现横切关注点的模块化。它允许开发者定义“切面”,将那些与业务逻辑无关,却为多个对象共有的行为(如日志、...
一、适合人群 1、具备一定Java编程基础,初级开发者 2、对springboot,mybatis,mysql有基本认识 3、对spring aop认识模糊的,不清楚如何实现Java 自定义注解的 ...4、spring boot,mybatis,druid,spring aop的使用
切面类中可以包含多个通知(Advice),包括前置通知(Before)、后置通知(After)、返回通知(After-returning)、异常通知(After-throwing)和环绕通知(Around)。通知指定了在目标方法执行的特定位置执行的额外...
**Spring AOP 配置实现详解** Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的重要组成部分,它允许我们通过分离关注点来简化应用程序的开发。在传统的面向对象编程中,业务逻辑与日志记录...