如何将记录器注入示例Spring启动应用程序中的字段?

vic*_*vic 13 java logging spring autowired spring-boot

我想要的是让spring autowire成为记录器.所以,换句话说,我想让这个工作:

import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MainController {

    @Autowired
    private Logger logger;

    @RequestMapping("/")
    public String enterSite(HttpServletResponse response) {
        logger.info("site entered");
        return "welcome";
    }
}
Run Code Online (Sandbox Code Playgroud)

现在它在启动时抛出异常:"找不到类型[org.slf4j.Logger]的限定bean用于依赖...".

我的pom.xml依赖项:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.0.M1</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

        <dependency>
            <groupId>postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.1-901.jdbc4</version>
        </dependency>
        <!-- <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> 
            </dependency> -->
    </dependencies>
Run Code Online (Sandbox Code Playgroud)

我看了这个

http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-logging

它说如果你使用其中一个起动器poms(我愿意)使用Logback - 但是用于内部记录.它可以在我的班级中自动装配吗?

Sim*_*ins 21

如果这里的目标是减少代码,那么尝试Project Lombok.然后,您甚至不需要声明记录器 - 只需添加注释并使用log而不是logger

所以你上面的代码现在看起来像这样:

import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
// import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
public class MainController {

    @RequestMapping("/")
    public String enterSite(HttpServletResponse response) {
        log.info("site entered");
        return "welcome";
    }
}
Run Code Online (Sandbox Code Playgroud)

  • “这并不能真正回答问题”[_sic_]。你是对的。因此,我的评论中的警告是:_这里没有注入机制。_以及我的解决方案之前的推测性假设声明:_如果这里的目标是代码减少..._我试图再次猜测需求背后的动机并提供帮助。我同意这并没有从法律条文上回答问题。 (2认同)

fl4*_*l4l 11

虽然通常的方式是你可以直接在上下文中添加一个记录器bean来重现经典绑定:

private final Logger logger = LoggerFactory.getLogger(MainController.class);
Run Code Online (Sandbox Code Playgroud)

只需插入弹簧上下文:

<bean id="logger" scope="prototype" class="org.slf4j.LoggerFactory" factory-method="getLogger">
    <constructor-arg name="name" value="youLoggerName" />
</bean>
Run Code Online (Sandbox Code Playgroud)

然后你可以简单地注入你的记录器:

@Autowired
private Logger logger;
Run Code Online (Sandbox Code Playgroud)


Dhe*_*rik 11

解决方案使用@Bean

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.InjectionPoint;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
public class LoggerConfiguration {

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Logger logger(InjectionPoint injectionPoint){
        return LoggerFactory.getLogger(injectionPoint.getMethodParameter().getContainingClass());
    }

}
Run Code Online (Sandbox Code Playgroud)

之后,只需使用构造函数注入(字段注入不起作用)注入 Logger :

@Service
class SomeService {

    private Logger logger;

    public SomeService(Logger logger;) {
        this.logger = logger;
    }

    public void someMethod() {
        logger.error("Some log");
    }  
}
Run Code Online (Sandbox Code Playgroud)

  • 有关处理方法参数注入和字段注入的示例,请参阅本文:https://medium.com/simars/inject-loggers-in-spring-java-or-kotlin-87162d02d068 (2认同)

And*_*son 6

可以让Spring自动装配一个Logger实例,但这是一件非常不寻常的事情(你需要一个类型的bean Logger才能在你的应用程序上下文中).更常见的方法是初始化它声明的记录器,使用将用于记录的类配置它:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MainController {

    private final Logger logger = LoggerFactory.getLogger(MainController.class);

}
Run Code Online (Sandbox Code Playgroud)

  • 不回答问题并鼓励在DI环境中使用不良行为. (9认同)