spring学习笔记2--bean装配

这篇博客详细介绍了Spring的bean装配机制,包括XML配置、自动装配、条件化bean、处理装配歧义性和不同作用域的使用。重点讲解了@Autowired、@Inject和@Resource注解的区别以及如何在不同场景下选择使用。此外,还探讨了会话和请求作用域的bean管理以及如何在运行时注入值。
摘要由CSDN通过智能技术生成

bean装配

Spring提供了三种主要的装配机制:

  • 在XML中进行显式配置。
  • 在Java中进行显式配置。
  • 隐式的bean发现机制和自动装配

自动装配

Spring从两个角度来实现自动化装配:

  • 组件扫描(component scanning):Spring会自动发现应用上下文
    中所创建的bean。
  • 自动装配(autowiring):Spring自动满足bean之间的依赖。
@Component
public class TestBean{

}
@Configuration
@ComponentScan
public class ConfigBean{

}

@ComponentScan开启组件扫描,如果没有其它配置默认会扫描与配置类相同的包及其子包。也可以是使用xml开启:

<contest:component-scan base-package="x.x.x"/>

使用spring创建一个测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=someclass.class)
public class Test{
    @AutoWire
    private TestClass test;
    @Test
    public void test(){
        Assert.assertNotNull(test);
    }
}

bean id

spring应用上下文会为所有的bean设定一个id,默认为类名的第一个字母小写。如果想自己设置,可以:

@Component("myid")

也可以:

Named("myid") public class myclass

扫描基础包

@Configuration
@ComponentScan(basePackages={"pacakge1","pacakge2"})
public class ConfigBean{

}

另外一种指定包扫描的方法为:

@ComponentScan(basePackageClasses={A.class,B.class})
这些类所在的包将会成为组件扫描的包。

自动装配

@Autowired注解可以用在构造器,Setter方法或者其它方法,spring会尝试满足方法参数上所声明的依赖。假如有且只有一个bean匹配,那么它将会被这个bean装配进来。如果没有则会抛出异常。为了避免异常,可以:

@Autowired(required=false)

如果有多个bean符合需求,也会抛出异常。

@Inject:java依赖注入规范定义的一个注解。也可以用来自动装配。

@Autowired和@Inject,@Resource

  1. @Autowired和@Inject
    默认 autowired by type
    可以 通过@Qualifier 显式指定 autowired by qualifier name。
  2. @Resource
    默认 autowired by field name
    如果 autowired by field name失败,会退化为 autowired by type
    可以 通过@Qualifier 显式指定 autowired by qualifier name
    如果 autowired by qualifier name失败,会退化为 autowired by field name。但是这时候如果 autowired by field name失败,就不会再退化为autowired by type了。
  3. @Autowired和@Inject基本是一样的,因为两者都是使用AutowiredAnnotationBeanPostProcessor来处理依赖注入。但是@Resource是个例外,它使用的是CommonAnnotationBeanPostProcessor来处理依赖注入。
  4. @Inject是jsr330规范的实现,而@Autowired是spring的实现,@Resource则是jsr250的实现。

显示装配bean

java方式:在添加了@Configuration注解的配置类中添加方法返回该bean:

@Configuration
public class CDPlayerConfig {

  @Bean(name="xxxx")
  public CompactDisc compactDisc() {
    return new SgtPeppers();
  }
  //没有name属性的话bean的id默认为方法的名字
  @Bean
  public CDPlayer cdPlayer(CompactDisc compactDisc) {
    return new CDPlayer(compactDisc);
  }
}

可以使用多个注解类,如果一个注解类要用到其中的一个注解类的bean的话,可以使用@import导入.如果用到xml声明的bean,可以把相应的配置文件导入。

@Configuration
@Import(CDPlayerConfig.class)
@ImportResource("classpath:cd-config.xml")
public class SoundSystemConfig {

}

在xml中如何引用javaconfig配置的bean? 可以使用标签将配置类导入。就可使用了。也可以创建一个组合xml,将配置文件和配置类一起导入,即根配置,并在根配置中启动组件扫描。

<bean class="soundsystem.CDConfig" />

  <bean id="cdPlayer"
        class="soundsystem.CDPlayer"
        c:cd-ref="compactDisc" />

创建一个根配置

<beans xmlns="">
<bean class="xxxConfig/>
<import resource="xxx.xml"/>
</beans>

条件化bean

@Bean
  @Conditional(MagicExistsCondition.class)
  public MagicBean magicBean() {
    return new MagicBean();
  }
  ```

传给该注解的类可以是任意实现了Condition接口的实现类。该接口根据matches返回的结果来决定是否实例化bean.
public inteface Condition{
    boolean matches(ConditionContext ctx,AnnotatedTypeMedtadata metadata);
}

@Profile也使用了@Conditional注解,并且引用ProfileCondition作为Condition实现。

处理自动装配歧义性

当有多个bean满足装配的条件时,如何解决?
有多种方法:
1. 首选bean.使用@Primary注解。当使用xml时可指定的primary属性为true.
2. 使用@Qualifier(“beanid”)指定bean的id.标识唯一性。如果没有则会使用默认的限定符命名方式。在bean声明上添加@Qualifier注解。例
如,它可以与@Component组合使用.

@Component
@Qualifier("xxxx")
public class testBean{

}

spring bean的常见作用域

  • 单例(Singletion)
  • 原型(Prototype)
  • 会话(Session)
  • 请求(Request)

声明作用域:

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

使用会话和请求作用域

@Component
@Scope{
value=WebApplicationContext.SOCPE_SESSION,
proxyMode=ScopedProxyMode.INTERFACES)
}
public ShoppingCart cart(){...}

proxyMode解决了这样一个问题,:将会话范围内的bean注入到单例bean中时,如果用户没有请求系统会话bean不存在或多个用户就会有多分session bean。使用proxyMode便会注入一个代理,当真正调用会话bean的方法时,代理会对其进行懒解析并将调用委托
给会话作用域内真正的ShoppingCart bean。,proxyMode属性被设置成了
ScopedProxyMode.INTERFACES,这表明这个代理要实现
ShoppingCart接口,并将调用委托给实现bean。如果ShoppingCart是类的话,要将proxyMode属性设置
为ScopedProxyMode.TARGET_CLASS,以此来表明要以生成目标
类扩展的方式创建代理。

在xml中声明作用域代理
<bean id="cart" class="com.myapp.ShoppingCart" scope="session">
<aop:scoped-proxy/>
</bean>

默认情况下,它会使用CGLib创建目标类的代理。但是我们也可
以将proxy-target-class属性设置为false,进而要求它生成基
于接口的代理:

运行时值注入

声明属性源并通过spring的Enviroment来检索属性:

@Configuration
@PropertySource("classpath:xxx.properties")
public class Config{
    @Autowired
    Enviroment ev;

    @Bean
    public Person person(){
        return new Person(env.getProperty("name"),evn.getProperty("id"));
    }
}

在java配置或xml配置中也可使用占位符的形式。
如果使用组件扫描和自动装配,则用@Value注解

public Person(@Value("${person.id}")String id,
    @Value("${person.name}")String name){
        this.id=id;
        this.name = name;
    }

为了使用占位符,必须配置一个PropertySourcePlaceholderConfigurer.

@Bean
public static PropertySourcePlaceholderConfigurer placeholderConfigurer(){
    return new PropertySourcePlaceholderConfigurer();
}

xml中的会为你生成PropertySourcePlaceholderConfigurer.

junit基于控制台的输出编写断言:

@Rule
public final StandardOutputStreamLog log = new StandardOutputStreamLog();

@Test
public void test(){
    assertEquals("some log",log.getLog());
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值