@Scope
在使用@Bean的时候,默认@Bean定义出来的注解是单例的,那么有什么方式可以指定它的范围呢,我们使用@Scope。Bean的作用域包括singleton、prototype、request、session、global session。
@Scope里边的内容和我们之前说到的Bean的范围是一样的,默认value是singleton,可以使用prototype、request、session、global session。
在@Scope里边还有另外一个属性proxyMode,即采用哪一种的代理方式,一种是基于接口的注解,还有一种是TARGET_CLASS,是对于类的代理。
然后看个例子,还是在前一篇的基础上,在StoreConfig中有这样的代码
@Bean(name = "stringStore")
@Scope(value="prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Store stringStore() {
return new StringStore();
}
设置value为prototype,它的意思是每一次请求都会创建一个新的对象。
写一个单元测试的方法
@Test
public void testScope() {
Store store = super.getBean("stringStore");
System.out.println(store.hashCode());
store = super.getBean("stringStore");
System.out.println(store.hashCode());
}
这里边取两次对象,输出对象hashCode看是否相同。若两次不同则为正确。
基于泛型的自动装配
@Configuration
public class MyConfiguration{
@Bean
public StringStore stringStore(){
return new StringStore();
}
@Bean
public IntegerStore integerStore(){
return new IntegerStore();
}
}
仍然是@Configuration配置两个类StringStore和IntegerStore。
@Autowired
private Store<String> s1;
@Autowired
private Store<Integer> s2;
在进行@Autowired自动装配的时候,两个Store s1和s2,第一个是String第二个是Integer。也就是说通过这种泛型的方式来指定s1和s2分别对应哪一个bean。s1泛型里边指定的是String,那么s1对应的应该是上边的StringStore,s2对应IntegerStore。
还有另一种方法
@Autowired
private List<Store<Integer>> s;
也就是说在一个集合里边的Store对象泛型指定的都是Integer类型的。
例子
将之前的一些类进行修改
接口里指定T泛型:
public interface Store<T> {}
然后在实现类指定它的泛型:
public class StringStore implements Store<String> {
public void init() {
System.out.println("This is init.");
}
public void destroy() {
System.out.println("This is destroy.");
}
}
写一个IntegerStore实现Store接口并指定它的泛型
public class IntegerStore implements Store<Integer> {}
在StoreConfig类中进行声明
@Autowired
private Store<String> s1;
@Autowired
private Store<Integer> s2;
@Bean
public StringStore stringStore() {
return new StringStore();
}
@Bean
public IntegerStore integerStore() {
return new IntegerStore();
}
@Bean(name = "stringStoreTest")
// public StringStore stringStoreTest() {
public Store stringStoreTest() {
System.out.println("s1 : " + s1.getClass().getName());
System.out.println("s2 : " + s2.getClass().getName());
return new StringStore();
}
里边有一个方法输出s1和s2的类名。这个方法要注意,由于是借用之前的写过的方法,所以类型是StingStore,但是s1在装配的时候发现有两个StringStore类型。正常情况下会把第一个@Bean注解的StringStore赋值给s1,但是有两个StringStore,会失败。所以把下边的方法类型修改一下。
单元测试类:
@Test
public void testG() {
StringStore store = super.getBean("stringStoreTest");
}
getBean的时候就会得到StoreConfig中的stringStoreTest方法,还会输出s1和s2两个类的类名。输出s1对应的StringStore,s2对应IntegerStore。
Autowire扩展内容,关于自定义qualifier注解
CustomeAutowireConfigurer是BeanFactoryPostProcessor的子类,通过它可以注册自己的qualifier注解类型(即使没有使用Spring的@Qualifier注解)
<bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>example.CustomQualifier</value>
</set>
</property>
</bean>
class指定类,这个类中有个属性customQualifierTypes,具体有哪些类型,我们可以把自己定义的类型放在里边,注意这里是Set,也就是说我们可以放很多个。
该AutowireCandidateResolver决定自动装配的候选者:
-每个bean定义的autowire-candidate值
-任何
<bean/>
中的default-autowire-candidates
-@Qualifier注解及使用CustomAutowireConfigurer的自定义类型。
很少会使用到