Spring 代理没有调用我的方法

Spring Proxy doesn't call my method

我是第一次尝试 AOP,为此我开发了一个简单的小示例,但我发现了一些问题。首先,Spring 要求我通过打印以下错误来向 cglib 库添加依赖项:

cannot proxy target class because cglib2 is not available

解决该问题并将依赖项添加到我的 pom.xml 文件后:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2</version>
</dependency>

我发现 cglib 为我的每个 bean 创建了一个代理,并且这些方法没有被执行。在这里你可以看到:

Class一个: 包裹 com.test.test.classes;

public abstract class A {
    public abstract void doMoreStuff();

    public void doStuff(){
        System.err.println("Inside A.doStuff()");
    }
}

Class B 包裹 com.test.test.classes;

public class B extends A{
    @Override
    public void doMoreStuff() {
        System.err.println("Inside B.doMoreStuff()");
   }
}

Class C 包裹 com.test.test.classes;

public class C extends A{
    @Override
    public void doMoreStuff() {
        System.err.println("Inside C.doMoreStuff()");
   }
}

看点 包裹 com.test.test.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AspectAttempt {
    @Around("execution(* com.test.test.classes.*.*(..))")
    public void miAspecto(ProceedingJoinPoint joinPoint) throws Throwable{
        System.err.println("Inside the Aspect");
        System.err.println("Invoking " + joinPoint.getSignature());
    }   
}

Spring 上下文

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "
    default-autowire="byName">

    <aop:aspectj-autoproxy proxy-target-class="false"/>

    <bean id="a1" class="com.test.test.classes.B" />
    <bean id="a2" class="com.test.test.classes.C" />
    <bean id="b" class="com.test.test.classes.B" />
    <bean id="c" class="com.test.test.classes.C" />

    <!-- Aspect -->
    <bean id="logAspect" class="com.test.test.aspect.AspectAttempt" />

</beans>

测试 包裹 com.test.test.testingAspects;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.test.test.classes.A;
import com.test.test.classes.B;
import com.test.test.classes.C;

/**
 * Unit test for simple App.
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { 
        "classpath:/context.xml" })
public class AppTest  {

    @Autowired
    @Qualifier("a1")
    private  A a1;
    @Autowired
    @Qualifier("a2")
    private  A a2;
    @Autowired
    @Qualifier("b")
    private  B b;
    @Autowired
    @Qualifier("c")
    private  C c;

    @Test
    public void test() {

        a1.doStuff();
        a2.doStuff();
        a1.doMoreStuff();
        a2.doMoreStuff();
        b.doStuff();
        b.doMoreStuff();
        c.doStuff();
        c.doMoreStuff();    
    }
}

控制台日志

29-oct-2015 10:47:33 org.springframework.test.context.TestContextManager retrieveTestExecutionListeners
INFO: @TestExecutionListeners is not present for class [class com.test.test.testingAspects.AppTest]: using defaults.
29-oct-2015 10:47:33 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [context.xml]
29-oct-2015 10:47:33 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@149eb9f: startup date [Thu Oct 29 10:47:33 CET 2015]; root of context hierarchy
29-oct-2015 10:47:33 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@40afb9: defining beans [org.springframework.aop.config.internalAutoProxyCreator,a1,a2,b,c,logAspect,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor]; root of factory hierarchy
Inside the Aspect
Invoking void com.test.test.classes.A.doStuff()
Inside the Aspect
Invoking void com.test.test.classes.A.doStuff()
Inside the Aspect
Invoking void com.test.test.classes.B.doMoreStuff()
Inside the Aspect
Invoking void com.test.test.classes.C.doMoreStuff()
Inside the Aspect
Invoking void com.test.test.classes.A.doStuff()
Inside the Aspect
Invoking void com.test.test.classes.B.doMoreStuff()
Inside the Aspect
Invoking void com.test.test.classes.A.doStuff()
Inside the Aspect
Invoking void com.test.test.classes.C.doMoreStuff()
29-oct-2015 10:47:36 org.springframework.context.support.AbstractApplicationContext doClose
INFO: Closing org.springframework.context.support.GenericApplicationContext@149eb9f: startup date [Thu Oct 29 10:47:33 CET 2015]; root of context hierarchy
29-oct-2015 10:47:36 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@40afb9: defining beans [org.springframework.aop.config.internalAutoProxyCreator,a1,a2,b,c,logAspect,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor]; root of factory hierarchy

知道问题出在哪里吗?

提前致谢

据我所知,最终方法未被调用,因为所有方法都被您的 AspectAttempt Aspect 捕获,但执行没有继续。

因此,如果您想继续进行真正的通话,您需要在 AspectAttempt.miAspecto 中像这样编辑:

@Aspect
public class AspectAttempt {
    @Around("execution(* com.test.test.classes.*.*(..))")
    public void miAspecto(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Inside the Aspect");
        System.out.println("Invoking " + joinPoint.getSignature());
        joinPoint.proceed();
    }
}

看到唯一新的是 jointPoint.proceed() 调用。

希望对您有所帮助。

spring reference:

Around advice is declared using the @Around annotation. The first
parameter of the advice method must be of type ProceedingJoinPoint. 
Within the body of the advice, calling proceed() on the 
ProceedingJoinPoint causes the underlying method to execute