@Scope
我们大家都知道Spring容器中注册了一个Bean,在默认情况下都是单实例的,我们可以来验证一下,继续沿用我们之前的例子。下面是我们的配置类
@Configuration
@ComponentScan(value = "com.test")
public class TestConfig {
@Scope
@Bean
public Dog dog(){
return new Dog("金毛",3);
}
}
然后我们在测试类中进行测试
public class TestMain {
@Test
public void test(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfig.class);
Object dog1 = applicationContext.getBean("dog");
Object dog2 = applicationContext.getBean("dog");
System.out.println(dog1 == dog2);
}
}
打印结果为:true
那我们希望我们的Bean设置为多实例怎么办呢?那就需要用到我们的@Scope注解了。
我们可以看到@Scope共有四个取值,其中prototype就是我们的多实例,让我们来验证一下
@Configuration
@ComponentScan(value = "com.test")
public class TestConfig {
@Scope("prototype")
@Bean
public Dog dog(){
return new Dog("金毛",3);
}
}
再次运行我们的测试类,打印结果为: false
另外我们需要注意,我们的多实例Bean其实是懒加载的,就是IOC容器启动时并不会去调用方法创建对象,而是每次获取的时候才回去创建一个对象。我们接下来去验证一下,首先我们将Dog类的构造方法都打印一句话,便于我们查看结果
public class Dog {
private String name;
private int age;
public Dog() {
System.out.println("调用无参构造方法...");
}
public Dog(String name, int age) {
System.out.println("调用有参构造方法...");
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
接下来配置类中将Bean改为单实例
@Configuration
@ComponentScan(value = "com.test")
public class TestConfig {
@Scope("singleton")
@Bean
public Dog dog(){
return new Dog("金毛",3);
}
}
最后我们运行测试类
public class TestMain {
@Test
public void test(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanName : beanDefinitionNames)
System.out.println(beanName);
}
}
结果为:
调用有参构造方法...
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
testConfig
userController
userDao
userService
dog
我们看见构造方法的确被调用了,所以单例的Bean在IOC容器启动的时候就会调用方法去创建对象,并放到IOC容器中,以后每次获取直接取获取就可以了,接下来我们去看看多实例,只需将配置类中的Scope的参数改成prototype即可
@Configuration
@ComponentScan(value = "com.test")
public class TestConfig {
@Scope("prototype")
@Bean
public Dog dog(){
return new Dog("金毛",3);
}
}
运行上述的测试类,可以发现结果如下:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
testConfig
userController
userDao
userService
dog
发现Dog的构造方法的确没有被调用。那我们在测试类中调用下多实例试试
public class TestMain {
@Test
public void test(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanName : beanDefinitionNames)
System.out.println(beanName);
System.out.println("-------------------------------");
applicationContext.getBean("dog");
for (String beanName : beanDefinitionNames)
System.out.println(beanName);
}
}
运行结果如下:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
testConfig
userController
userDao
userService
dog
-------------------------------
调用有参构造方法...
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
testConfig
userController
userDao
userService
dog
我们可以清楚地发现,并验证我们上述有关@Scope的有关的特征。
@Lazy
现在我们万一想要要求单实例Bean懒加载了怎么办呢·,这时候我们就可以使用@Lazy注解了,这个注解肯定是针对单实例的,因为多实例根本就不需要。
@Configuration
@ComponentScan(value = "com.test")
public class TestConfig {
@Scope("singleton")
@Lazy
@Bean
public Dog dog(){
return new Dog("金毛",3);
}
}
我们只需在需要进行懒加载处理的方法上加上@Lazy注解即可,验证方法如上一致,可执行验证。
来源:https://blog.csdn.net/newbie0107/article/details/99692652