(七)、Bean

声明Bean

在spring容器中,声明bean有两种方式,一种是@Bean,另一种是@Component注解(包括@Service、@Controller、@Repository、@Configuration)。

  • 对于@Bean注解,如果指定了name参数,以参数为准;如果未指定name参数,会以方法名作为bean的名称。
  • 对于@Component注解,如果指定了参数,以参数为准;如果未指定参数,会以类名作为bean的名称;如果类名开头是两个或者两个以上大写字母,bean名同类名完全一致;如果开头只有一个大写字母,bean名是类名首字母小写版。

Bean的作用域

  • Scope(“singleton”):单例模式,即每次调用将使用同一个bean实例,spring的默认scope。
  • Scope(“prototype”):原型模式,每次获取这个bean都会创建一个新的实例。
  • Scope(“request”):在web应用中,给每个请求创建一个bean实例。
  • Scope(“session”):在web应用中,给每个会话创建一个bean实例。

例子:

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Test {  ... }

这里使用了ConfigurableBeanFactory.SCOPE_PROTOTYPE,当然也可以使用“prototype”。

下面说一下Scope为session的例子:

@Component
@Scope(
    value=WebApplicationContext.SCOPE_SESSION,
    proxyMode=ScopedProxyMode.INTERFACES
)
public class TestImpl implements Test {  ... }

@Service
public class T {
    @Autowired
    private Test test;
}

因为T是一个单例的bean,但是,Test是会话类型的,所以T中要调用会话对应的bean,如何指定呢?这时proxyMode就派上用场了。ScopedProxyMode.INTERFACES表明这个的代理要实现Test接口(必须是接口),并将调用委托给bean实现。作用域代理能够延迟注入请求和会话作用域的bean。

流程图: 单例bean <— 接口(作用域代理) <— 接口(会话、请求作用域的bean)

注意: 如果是类的话必须使用CGLib来生成基类的代理,并把proxyMode属性设置成ScopedProxyMode.TARGET_CLASS,表明要以生成目标类扩展的方式创建代理。

Bean的线程安全问题

  • singleton:是无状态的bean,解决线程安全问题就是bean里不会定义有状态的变量,如果必须有成员变量,可以用ThreadLocal修饰。
  • prototype:每次都是一个新bean,显然没有线程安全问题
  • request和session对象:除非显示的使用多线程,需要注意一下线程安全问题,在大多数情况,bean都是线程安全的。

Bean对象初始化钩子

@PostConstruct:会在bean初始化前调用,@PreDestroy:会在bean销毁前调用,其实@Bean注解有initMethod和destroyMethod属性。

Bean注入

使用@Autowired注解。@Autowire(required = false)表名被注入对象能为null。
如果一个服务有多个实现,spring是不能识别出该注入那个实现的,这时@Primary和@Qualifer注解就派上用场了。
@Primary标志着是首选bean,也就是当service有多个实现时,没有指明注入那个时,默认选择有@Primary注解所在Service。
@Qualifer指定选择的bean的id

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值