配置Bean
【Spring Boot将类作为bean使用】
【解决方法】使用@ComponentScan自动检测类并创建类的实例,该注解与@Autowired和@Value一起使用以获取依赖项或注入的属性;或者可以使用注解@Bean,这种方法可以对正在创建的bean的构造过程获取更多的控制。
工作原理:
@SpringBootApplication注解包含@ComponentScan和@Configuration 意味着@Component注解的类都将由Spring Boot自动检测和实例化,还允许使用@Bean来注解方法,从而将方法声明为bean。
1、使用@Component注解
创建需要实例化的类HelloWorld,并在类上面使用@Component注解
这样子当程序启动的时候,HelloWorld类就会被扫描到,进而实例化。
具体代码
@Component
public class HelloWorld {
public HelloWorld() {
System.out.println("HelloWorld constructor");
}
@PostConstruct
public void sayHello() {
System.out.println("postconstruct2");
}
}
程序执行是,当类实例化:会先执行构造方法->@PostConstruct 注解的方法
执行结果是
HelloWorld constructor
postconstruct2
2、使用@Bean注解
使用@Bean注解生成的bean的名称与方法的名称相同
创建一个对整数进行一些基本计算单应用程序。首先编写Calculator类,他将在构造函数中获得一组Operation bean。Operation是一个接口,多个不同的实现将进行实际计算。
其中Operation.handles方法检测正确的Operation,找到Operation后调用对应的apply方法。
@Bean Calculator calculator(Collection<Operation> operations)
class Calculator
Calculator(Collection<Operation> operations)
void calculate(int lhs, int rhs, char op)
interface Operation
int apply(int lhs, int rhs);
boolean handles(char op);
@Component Addition implements Operation
@Component Multiplication implements Operation
Bean calculator 方法接收参数List<Operation>,并使用参数来构造Calculator实例
当在@Bean注解方法中使用参数时,这些参数将被自动解析。当注入集合是,Spring自动检测所需bean的所有是咧,并使用这个集合调用calculator工厂方法。
通过用@Component注解类Calculator,就无需写 @Bean Calculator calculator(Collection<Operation> operations) 方法
外置配置文件
默认配置文件为 application.properties
可以设置不同的环境配置环境 比如 application-test.properties
在application.properties里面指定真实的配置文件
spring.profiles.active=add
测试
单元测试
在单元测试模拟依赖项
Springboot会自动引入Mockito框架 Junit4
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
public class CalculatorTest {
private Calculator calculator;
private Operation mockOperation;
@Before
public void setup() {
mockOperation = Mockito.mock(Operation.class);
calculator = new Calculator(Collections.singletonList(mockOperation));
}
@Test
public void test() {
//when().thenReturn()设置mock返回值
Mockito.when(mockOperation.handles('+')).thenReturn(false);
Mockito.when(mockOperation.handles('*')).thenReturn(true);
Mockito.when(mockOperation.apply(29,11)).thenReturn(29*11);
calculator.calulate(29, 11, '*');
//verify方法验证apply方法的调用次数,默认times(1),同时验证apply方法参数一致,
//为成功
Mockito.verify(mockOperation).apply(29,11);
}
}
集成测试
@SpringBootTest注解,将使测试成为SpringBoot驱动的一个测试,这意味着测试上下文框架将搜索用@SpringBootApplication注解的类(如果没有传递特定的配置),其中@SpringBootTest注解可以指定配置信息 @SpringBootTest(classes={applicaition.class})
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.lycoris.springbootrecipes.demo.calculator.Calculator;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTest {
@Autowired
private Calculator calculator;
@Test(expected = IllegalArgumentException.class)
public void test() {
calculator.calulate(20, 2, '/');
}
}
@SpringBootTest和Testng集合,@SpringBootTest注解同样指定配置文件,并且测试类extends
AbstractTestNGSpringContextTests类
@SpringBootTest(classes = { CoretestApplication.class })
public class Loan extends AbstractTestNGSpringContextTests {
public final Logger logger = LoggerFactory.getLogger(Loan.class);
@Autowired
private RestTemplate restTemplate;
//dao
@Autowired
private LoanDao loandao;
@Test
public void needTestCode(){
}
}
Spring Boot 2.2以后,默认的Junit5 如果要使用Junit4 需要额外引入 Junit4的包
POM文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
</exclusion>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
<exclusion>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
Junit注解@Rule
@Rule注解将配置指定的Junit规则,OutputCaptureRule为例,该规则已经集成到了spring boot中
@Rule
//JUnit {@code @Rule} to capture output from System.out and System.err.
public OutputCaptureRule output = new OutputCaptureRule();
@Autowired
private Calculator calculator;
@Test
public void doingAdditionShouldSucceed() {
calculator.calulate(20, 2, '+');
output.expect(Matchers.containsString("20 + 2 = 22"));
}
使用Spring Boot和模拟进行集成测试
通过模拟的方式替换bean--- @MockBean注解 替换multipliction同名的bean
@MockBean(name="multiplication")
private Operation mockOperation;
如果没有增加 名为multiplication2的bean
@MockBean(name="multiplication2")
private Operation mockOperation;