Spring 引入切面后容器不注入依赖
Spring container doesn't inject dependencies after the introduction of the aspect
该项目在使用AOP之前运行良好,但是在添加LoggingAspect
class之后,出现了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 对象变为空。确保通过你的 context.xml.What 将没有空引用的对象传递给 runner class 的构造函数 我在这里写的只是为了将 eventLogger 对象传递给 Runner class 的构造函数。您还必须对构造函数的其他两个参数执行相同的操作。请务必与我们分享您的结果。
<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>
错误已更正,感谢对此问题的评论。
我把私有方法logEvent
class Runner改成了public!我会解释为什么这有效,但我不太明白为什么。如果我知道,我会在这个答案的评论中留下解释。
public void logEvent(EventType type, Event message) {
EventLogger eventLogger;
if (type == null) eventLogger = defaultLogger;
else eventLogger = loggers.get(type);
eventLogger.logEvent(message);
}
该项目在使用AOP之前运行良好,但是在添加LoggingAspect
class之后,出现了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 对象变为空。确保通过你的 context.xml.What 将没有空引用的对象传递给 runner class 的构造函数 我在这里写的只是为了将 eventLogger 对象传递给 Runner class 的构造函数。您还必须对构造函数的其他两个参数执行相同的操作。请务必与我们分享您的结果。
<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>
错误已更正,感谢对此问题的评论。
我把私有方法logEvent
class Runner改成了public!我会解释为什么这有效,但我不太明白为什么。如果我知道,我会在这个答案的评论中留下解释。
public void logEvent(EventType type, Event message) {
EventLogger eventLogger;
if (type == null) eventLogger = defaultLogger;
else eventLogger = loggers.get(type);
eventLogger.logEvent(message);
}