spring中的bean对象的有关了解
@Configuration public class AppConfig { @Bean public MyBean getMyBean() { MyBean myBean = new MyBean(); myBean.setName("Example"); return myBean; } // 其他的@Bean方法... }
上述是一个配置类,里面有个@Bean注解修饰,@Configuration
注解的类里面的方法在Spring容器启动时并不会立即执行,而是在需要获取被@Bean
注解标记的Bean实例时才会被调用。这样可以实现懒加载,只有在需要使用某个Bean时才去创建它。
如何获取到这个类呢
第一种:
@Autowired
private MyBean myBean;
第二种:
@Autowired
private ApplicationContext applicationContext;
public void someMethod() {
AppConfig appConfig= applicationContext.getBean(AppConfig.class);
MyBean myBean = appConfig.getMyBean();
// 使用获得的 MyBean 对象
}
需要注意的是默认情况下会注入同一个对象实例。这是因为被 @Bean
注解标记的方法的返回值默认是单例的,也就是说在整个应用程序的生命周期中,都会共享同一个对象实例。不管在哪个类里面调用,也都是同一个对象,
如果在任何地方重新对该对象 进行赋值,那么所有使用到这个对象的地方都会受到影响,因为它们引用的都是同一个对象实例
问题来了,当时多线程的时候,就会出现线程安全问题,对于这种线程安全问题,可以采取以下几种策略
- 使用同步机制:通过在关键代码块或方法上添加
synchronized
关键字,确保同一时间只有一个线程可以进入该代码块或方法public class ThreadSafeBean { private int count; public synchronized void increment() { count++; } public synchronized int getCount() { return count; } }
在上面的示例中,通过使用
synchronized
关键字修饰increment()
和getCount()
方法,确保在多线程环境下对count
属性的访问和操作是线程安全的 - 使用线程安全的数据结构:使用线程安全的数据结构,如
java.util.concurrent.atomic
包下的原子类,可以避免使用同步机制来实现线程安全。
public class ThreadSafeBean { private AtomicInteger count = new AtomicInteger(0); public void increment() { count.incrementAndGet(); } public int getCount() { return count.get(); } }
在上面的示例中,使用AtomicInteger
类来替代普通的int
类型,它提供了原子性操作,避免了使用synchronized
关键字来实现线程安全。
- 使用线程安全的容器:使用线程安全的容器来存储和访问
Bean
实例,确保多线程环境下的访问操作是线程安全的。import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.concurrent.ConcurrentHashMap; @Component public class ThreadSafeBeanContainer { private ConcurrentHashMap<String, ThreadSafeBean> beanMap; @Autowired public ThreadSafeBeanContainer() { beanMap = new ConcurrentHashMap<>(); } public void addBean(String name, ThreadSafeBean bean) { beanMap.put(name, bean); } public ThreadSafeBean getBean(String name) { return beanMap.get(name); } }
在上面的示例中,使用
ConcurrentHashMap
作为线程安全的容器来存储ThreadSafeBean
实例,并提供线程安全的访问方法。 - 使用线程安全的注解:Spring提供了一些线程安全的注解,例如
@Scope("prototype")
将bean的作用域设置为原型模式,每次请求都会创建一个新的实例,从而避免线程安全问题。@Component @Scope("prototype") public class UserService { private int count = 0; public void addUser() { count++; } public int getUserCount() { return count; } }