java - Spring容器引入aspect后不注入(inject)依赖

标签 java spring spring-aop

项目在使用AOP之前运行良好,但是添加LoggingAspect类后,出现了NullPointerException。我进行了项目调试,在出现 NullPointerException 时,没有任何对象可以调用方法。 defaultLogger 对象嵌入在 Runner 对象的构造函数中。为什么会发生这种情况? Link to the project

@Component
@Aspect
public class LoggingAspect {

    @Pointcut("execution(* *.logEvent(..))")
    public void allLogEventMethods() {}

    @Before("allLogEventMethods()")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("BEFORE: " +
                joinPoint.getTarget().getClass().getSimpleName() + " " +
                joinPoint.getSignature().getName());
    }

    @AfterReturning(pointcut="allLogEventMethods()",
            returning="retVal")
    public void logAfter(Object retVal) {
        System.out.println("AFTER_RET: " + retVal);
    }

    @AfterThrowing(pointcut="allLogEventMethods()",
            throwing="ex")
    public void logAfterThrow(Throwable ex) {
        System.out.println("AFTER_THR: " + ex);
    }
}

@Component
public class Runner {
    private Client client;
    private EventLogger defaultLogger;
    private Map<EventType, EventLogger> loggers;

    @Autowired
    public Runner(
            Client client,
            EventLogger defaultLogger,
            Map<EventType, EventLogger> loggerMap) {
        this.client = client;
        this.defaultLogger = defaultLogger;
        this.loggers = loggerMap;
    }

    public static void main(String[] args) {
        ConfigurableApplicationContext ac = 
            new ClassPathXmlApplicationContext("context.xml");
        Runner app = ac.getBean(Runner.class);
        Event event;
        int i = 0;
        while (i < 10) {
            event = ac.getBean(Event.class);
            event.setMessage("Some event for " + i++);
            app.logEvent(null, event);
        }
        while (i < 20) {
            event = ac.getBean(Event.class);
            event.setMessage("Some event for " + i++);
            app.logEvent(EventType.INFO, event);
        }
        while (i < 30) {
            event = ac.getBean(Event.class);
            event.setMessage("Some event for " + i++);
            app.logEvent(EventType.ERROR, event);
        }

        ac.close();
    }

    private void logEvent(EventType type, Event message) {
        EventLogger eventLogger;
        if (type == null) eventLogger = defaultLogger;
        else eventLogger = loggers.get(type);
        eventLogger.logEvent(message);                //NullPointerException
    }
}

相关对象用@Component("defaultLogger")注释

@Component("defaultLogger")
public class CacheFileLogger extends FileLogger {
    private int cacheSize;
    private List<Event> events;

    public CacheFileLogger(
            @Value("${filename}") String filename,
            @Value("${cacheSize}") int cacheSize
    ) {
        super(filename);
        this.cacheSize = cacheSize;
        events = new ArrayList<>(cacheSize);
    }

    @Override
    public void logEvent(Event event) {
        events.add(event);
        if (cacheSize == events.size()) {
            writeAndClearCache();
        }
    }

    private void writeAndClearCache() {
        for (Event event1 : events) {
            super.logEvent(event1);
        }
        events.clear();
    }

    @PreDestroy
    private void destroy() {
        if (!events.isEmpty()) {
            writeAndClearCache();
        }
    }
}

文件 context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <context:annotation-config/>
    <context:component-scan base-package="by.babanin"/>
    <aop:aspectj-autoproxy/>
</beans>

Debug image

最佳答案

当您调用 logEvent 方法时,您的 eventLogger 对象将变为 null。确保通过 context.xml 将没有空引用的对象传递给 Runner 类的构造函数。我在这里编写的内容仅用于将 eventLogger 对象传递给 Runner 类的构造函数。您还必须对构造函数的其他两个参数执行相同的操作。请务必与我们分享您的结果。

<bean id="Runner" class="com.xyz.abc.Runner">
    <property name="EventLogger ">
      <bean class="com.xyz.abc.EventLogger ">
        <property name="param1" value="value1" />
        <property name="param2" value="value2" />
        <property name="param3" value="value3" />
      </bean>
    </property>
</bean>

关于java - Spring容器引入aspect后不注入(inject)依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56682649/

相关文章:

java - 为什么不满足这个条件?

java - Spring Boot 1.5.8 中的内存泄漏

spring - 如何在Aop中打印Grails Controller 参数对象值

java - Spring AOP 命名切入点到底是如何工作的?有何用途?

spring - 在方法上具有 @Retryable 注释的模拟 Spring @Service 失败并出现 UnfinishedVerificationException

java - 如何在 JUnit 测试中强制 Autowiring ?

java - 用于合并 java bean 的工具

Java kill 3线程转储输出重定向

java - 使用 swagger-spring-JAVA 时,@pathVariable 中的重音字符未正确解码

spring - 当尝试从非 Artefact Groovy 文件中的静态方法访问服务时,在静态作用域中发现了明显的变量 'serviceName'