在Spring框架中,@Configuration注解用于声明一个Java类作为配置类,它替代了传统的XML配置方式。通过@Configuration注解标记的类可以包含@Bean注解,用于定义Spring容器中的Bean对象。而在@Configuration注解中,有一个非常重要的属性proxyBeanMethods,它控制着@Configuration类中@Bean方法的代理行为。让我们对这个属性进行非常详细的介绍:
@Configuration注解:
@Bean注解:
proxyBeanMethods属性:
代理模式(Proxy Mode):
禁用代理模式:
如何选择代理模式:
示例代码:
@Configuration
public class MyConfiguration {
@Bean
public MyBean myBean() {
return new MyBean();
}
@Bean
public AnotherBean anotherBean() {
return new AnotherBean(myBean());
}
}
总结:
@Configuration注解用于声明配置类,其中的@Bean注解用于定义Spring容器中的Bean对象。proxyBeanMethods属性控制@Bean方法的代理行为。启用代理模式可以提高性能,禁用代理模式可以保证每次调用@Bean方法都返回新的实例。选择是否启用代理模式取决于应用程序的需求。
##二. 场景再现
为了更好地理解proxyBeanMethods的不同使用场景,我们创建一个简单的示例来演示它们的效果。我们将创建一个Spring应用程序,其中包含一个@Configuration类,其中定义了两个@Bean方法,并在不同场景下测试proxyBeanMethods的行为。
场景一:启用代理模式
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = true)
public class ProxyEnabledConfiguration {
@Bean
public MyBean myBean() {
return new MyBean();
}
@Bean
public AnotherBean anotherBean() {
//开启代理,实例Bean会被缓存,直接返回已存在的Bean
return new AnotherBean(myBean());
}
}
场景二:禁用代理模式
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class ProxyDisabledConfiguration {
@Bean
public MyBean myBean() {
return new MyBean();
}
@Bean
public AnotherBean anotherBean() {
//禁用代理,每次都会生成新的实例Bean
return new AnotherBean(myBean());
}
}
MyBean.java:
public class MyBean {
private static int instanceCounter = 0;
private int instanceNumber;
public MyBean() {
instanceNumber = ++instanceCounter;
System.out.println("Creating MyBean instance: " + instanceNumber);
}
public int getInstanceNumber() {
return instanceNumber;
}
}
AnotherBean.java:
public class AnotherBean {
private MyBean myBean;
public AnotherBean(MyBean myBean) {
this.myBean = myBean;
System.out.println("Creating AnotherBean instance using MyBean with instance number: " + myBean.getInstanceNumber());
}
}
测试类:
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
// proxyBeanMethods enabled
AnnotationConfigApplicationContext context1 = new AnnotationConfigApplicationContext(ProxyEnabledConfiguration.class);
AnotherBean anotherBean1 = context1.getBean(AnotherBean.class);
// proxyBeanMethods disabled
AnnotationConfigApplicationContext context2 = new AnnotationConfigApplicationContext(ProxyDisabledConfiguration.class);
AnotherBean anotherBean2 = context2.getBean(AnotherBean.class);
}
}
在启用代理模式的场景中(ProxyEnabledConfiguration),MyBean只会被实例化一次,因为AnotherBean会复用已经创建的MyBean实例,从控制台输出可以看到:
Creating MyBean instance: 1
Creating AnotherBean instance using MyBean with instance number: 1
而在禁用代理模式的场景中(ProxyDisabledConfiguration),MyBean会被每次调用都实例化一次,因为没有缓存,从控制台输出可以看到:
Creating MyBean instance: 1
Creating MyBean instance: 2
Creating AnotherBean instance using MyBean with instance number: 1
Creating MyBean instance: 3
Creating AnotherBean instance using MyBean with instance number: 2
通过这两个场景的对比,我们可以清楚地看到proxyBeanMethods属性的影响。
概念性东西确实很绕,有时候我们想要探寻底层原理,往往会碰壁,但是,不能放弃,多读几遍,多查查资料,兼容众家之长,把它拿下,吸收,彻底理解,慢慢的,一步一步来,不要着急!!!