1、FactoryBean——Spring提供的一个特殊接口
FactoryBean接口是工厂Bean的标准接口,实现该接口的Bean通常作为工厂Bean使用,
当我们把工厂Bean部署在容器中、并通过getBean()方法来获取时,容器返回的不是FactoryBean实例,而是返回FactoryBean的产品(也就是该工厂Bean的getObject方法的返回值)。
实现FactoryBean接口要实现3个方法:
- Object getObject():该方法负责返回工厂的产品。
- getObjectType() :该方法返回产品的类型。
- isSingleton():该方法返回产品是否为单例。
eg:
实现FactoryBean接口获取任意类的、任意静态field的值
(1)GetFieldFactoryBean.java
public class GetFieldFactoryBean implements FactoryBean<Object>{
private String className;
private String targetField;
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getTargetField() {
return targetField;
}
public void setTargetField(String targetField) {
this.targetField = targetField;
}
@Override
public Object getObject() throws Exception {
//获取任意类的、任意静态field的值。
Class clazz = Class.forName(className);
Field field = clazz.getField(targetField);
// Field是静态的,不需要用对象即可获取值
return field.get(null);
}
// 多余的
@Override
public Class<?> getObjectType() {
return Object.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
Dinasaur.java
public class Dinosaur implements Dog{
//如果需要通过FactoryBean获取静态field的值,也需要提供get和set方法
public static int flag = 1;
public static int getFlag() {
return flag;
}
public static void setFlag(int flag) {
Dinosaur.flag = flag;
}
}
(2)beans.xml
<bean id="getField" class="cony.factory.GetFieldFactoryBean"
abstract="true"
/>
<bean id="val1" parent="getField"
p:className="cony.domain.Dinosaur"
p:targetField="flag"
/>
<bean id="val2" parent="getField"
p:className="java.sql.Connection"
p:targetField="TRANSACTION_SERIALIZABLE"
/>
(3)测试
ApplicationContext appContext = new ClassPathXmlApplicationContext("beans.xml");
System.out.println(appContext.getBean("val1"));
System.out.println(appContext.getBean("val2"));
测试结果:
2、 获取Bean的id
需要让Bean实现BeanNameAware接口以及实现该接口中setBeanName()方法。
eg:
(1)Puppy.java
public class Puppy implements ApplicationContextAware,BeanNameAware{
String kind;
private int age;
private ApplicationContext ctx;
private String beanId;
public void bark(){
System.out.println("提前获取的id: "+beanId);
System.out.println(ctx.getMessage("bark", null,Locale.getDefault(Category.FORMAT)));
}
@Override
public void setBeanName(String beanId) {
System.out.println("调用setBeanName方法");
this.beanId = beanId;
}
@Override
public void setApplicationContext(ApplicationContext ctx)
throws BeansException {
System.out.println("调用setApplicationContext方法");
this.ctx = ctx;
} public String getKind() {
return kind;
}
//setter、getter...
}
(2)beans.xml
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>mess</value>
</list>
</property>
</bean>
<bean id="puppy"
class="cony.domain.Puppy"
p:kind="牧羊犬"
p:age="9"
/>
(3)测试
ApplicationContext appContext = new ClassPathXmlApplicationContext("beans.xml");
Puppy puppy = appContext.getBean("puppy",Puppy.class);
puppy.bark();
System.out.println();
测试结果:可以看出setBeanName方法先于setApplicationContext方法被调用