Код: Выделить всё
package com.example;
//just a simple interface, nothing spring-related here
public interface Foo {
String addFoo(String foo);
}
Код: Выделить всё
package com.example;
//just a simple implementation, nothing spring-related here
public class FooImpl implements Foo {
@Override
public String addFoo(String foo) {
return "this is a foo WITHOUT dependency injection: " + foo;
}
}
Код: Выделить всё
package com.example;
// just a simple interface, nothing spring-related here
public interface MyThing {
Foo foo();
}
Код: Выделить всё
package com.example;
//just a simple implementation, nothing spring-related here
public class MyThingImpl implements MyThing {
private final FooImpl fooImpl;
public MyThingImpl(String importantConfiguration) {
System.out.println("this layer needs to get the @Configuration value to perform its logic: " + importantConfiguration);
fooImpl = new FooImpl(); //using "new" keyword here!
}
@Override
public Foo foo() {
return fooImpl;
}
}
Код: Выделить всё
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(final String[] args) {
SpringApplication.run(MyApplication.class);
}
}
Код: Выделить всё
package com.example;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfiguration {
@Value("${my.important.configuration}")
private String importantConfiguration;
@Bean
public MyThing myThing() {
// need to configure MyThingImpl bean with importantConfiguration from this layer. This layer should not be removed.
return new MyThingImpl(importantConfiguration); //using "new" keyword here!
}
}
Код: Выделить всё
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Optional;
@RestController
public class TestingSolutionOne {
private final MyThing myThing;
@Autowired
public TestingSolutionOne(MyThing myThingParam) {
// here, we inject the !configurable! MyThing bean via constructor injection
this.myThing = myThingParam;
}
@GetMapping(value = "/test")
public Optional mockFindById() {
String firstResult = myThing.foo().addFoo("testFoo");
System.out.println("First Result: " + firstResult);
return Optional.of(firstResult + "-");
}
}
Я могу настроить свой компонент с помощью конфигурации и на уровне контроллера, чтобы получить его и выполнить свою бизнес-логику.
Однако у меня возникают следующие проблемы. Мы используем несколько инструментов статического анализа, а также инструменты проверки кода AI, каждый из которых отличается от других компаний, всего их 6.
Все они получили одинаковые отзывы:
- Использование ключевого слова new здесь является антишаблоном Spring Boot. Следует использовать IoC, DI.
- Эта реализация имеет проблемы с памятью при использовании дизайна bean-компонентов Spring Boot.
Код: Выделить всё
package com.example;
//just a simple interface, nothing spring-related here
public interface Foo {
String addFoo(String foo);
}
Код: Выделить всё
package com.example;
import org.springframework.stereotype.Component;
@Component
// Now, I am marking this class as a Spring component
public class FooImpl implements Foo {
@Override
public String addFoo(String foo) {
return "this is a foo WITH dependency injection: " + foo;
}
}
Код: Выделить всё
package com.example;
// just a simple interface, nothing spring-related here
public interface MyThing {
Foo foo();
}
Код: Выделить всё
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
// Now, I am marking this class as a Spring component, and FooImpl bean should be injected, no "new" keyword needed
public class MyThingImpl implements MyThing {
@Value("${my.important.configuration:default}")
private String importantConfiguration;
private final FooImpl fooImpl;
@Autowired
public MyThingImpl(FooImpl foo) {
System.out.println("I am not able to get the configuration from the @Configuration layer anymore, since I cannot 'new MyThingImpl(configuration)'' " + importantConfiguration);
fooImpl = foo;
}
@Override
public Foo foo() {
return fooImpl;
}
}
Код: Выделить всё
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(final String[] args) {
SpringApplication.run(MyApplication.class);
}
}
Код: Выделить всё
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfiguration {
//Think I am doing it wrong here, the configuration cannot be passed to MyThingImpl
private final MyThing myThing;
@Autowired
public MyConfiguration(MyThingImpl myThingParam) {
this.myThing = myThingParam;
}
@Bean
public MyThing myThing() {
return this.myThing;
}
}
Код: Выделить всё
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Optional;
@RestController
public class TestingSolutionTwo {
private final MyThing myThing;
@Autowired
public TestingSolutionTwo(MyThing myThingParam) {
this.myThing = myThingParam;
}
@GetMapping(value = "/test")
public Optional mockFindById() {
String firstResult = myThing.foo().addFoo("testFoo");
System.out.println("First Result: " + firstResult);
return Optional.of(firstResult + "-");
}
}
Код: Выделить всё
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.TestingSolutionTwo required a single bean, but 2 were found:
- myThingImpl: defined in file [/Users/question/target/classes/com/example/MyThingImpl.class]
- myThing: defined by method 'myThing' in class path resource [com/example/MyConfiguration.class]
P.S. Если возможно, было бы здорово выделить недостатки решения 1. Пока я просто слепо доверяю и слежу за анализаторами, мне трудно понять, в чем проблема
Подробнее здесь: https://stackoverflow.com/questions/798 ... ed-a-singl
Мобильная версия