Как вставить регистратор в поле в примерном загрузочном приложении spring?
Я хочу сделать spring autowire 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;
@Controller
public class MainController {
@Autowired
private Logger logger;
@RequestMapping("/")
public String enterSite(HttpServletResponse response) {
logger.info("site entered");
return "welcome";
}
}
В настоящий момент он запускает исключение при запуске: "Не найден квалифицированный bean типа [org.slf4j.Logger], найденный для зависимости...".
Мои зависимости 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>
Я прочитал это
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-logging
В нем говорится, что если вы используете один из стартовых попов (я делаю), используется журнал, но для внутреннего ведения журнала. Можно ли его автоувеличивать в моих классах?
Ответы
Ответ 1
Хотя это не обычный способ, вы можете добавить logger bean прямо в свой контекст, воспроизводя классическое связывание:
private final Logger logger = LoggerFactory.getLogger(MainController.class);
просто вставляя в контекст spring:
<bean id="logger" scope="prototype" class="org.slf4j.LoggerFactory" factory-method="getLogger">
<constructor-arg name="name" value="youLoggerName" />
</bean>
то вы можете просто ввести ваш регистратор:
@Autowired
private Logger logger;
Ответ 2
Если целью здесь является сокращение кода, попробуйте 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";
}
}
Ответ 3
У вас может быть Spring autowire экземпляр Logger, но это было бы очень необычно (вам нужно, чтобы bean типа Logger
находился в вашем контексте приложения). Более обычный подход заключается в том, чтобы инициализировать регистратор, где он был объявлен, настроив его на класс, который будет использовать его для ведения журнала:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MainController {
private final Logger logger = LoggerFactory.getLogger(MainController.class);
}
Ответ 4
Решение с использованием @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());
}
}
После этого просто введите Logger с помощью Constructor Injection (вставка поля не будет работать):
@Service
class SomeService {
private Logger logger;
public SomeService(Logger logger;) {
this.logger = logger;
}
public void someMethod() {
logger.error("Some log");
}
}
Ответ 5
Вот как я получил это работает для полевой инъекции
LoggingConfiguration.java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class LoggingConfiguration {
@Bean
public Logger log() {
var log = LoggerFactory.getLogger("com.bitsmonkey.dummy");
return log;
}
}
Теперь внутри контроллера
DummyController.java
@Controller
public class DummyController {
@Autowired
private Logger log;
//......