依赖查找
根据名称进行查找
- 实时查找
BeanFactory beanFactory = new ClassPathXmlApplicationContext("beans.xml");
Object bean = beanFactory.getBean("personHolder");
System.out.println(bean);
xml如下:
<bean id="person" class="pojo.Person">
<property name="name" value="yong"></property>
<property name="id" value="1001"></property>
</bean>
<bean id="personHolder" class="pojo.PersonHolder" >
<property name="city" value="BEIJING"></property>
<property name="person" ref="person"></property>
</bean>
- 延迟查找
所谓延迟查找其实就是我们使用到这个Bean的时候再去进行查找。
通过xml配置的方式:
<!-- 这里指定了查找方式为延迟查找也就是说在需要用到这个bean的时候才会初始化 -->
<bean id="personHolder" class="pojo.PersonHolder" lazy-init="true" init-method="init">
<property name="city" value="BEIJING"></property>
<property name="person" ref="person"></property>
</bean>
通过注解的方式:
@Bean
@Lazy
PersonHolder personHolder(Person person) {
return new PersonHolder(person);
}
通过ObjectProvider的方式:
/**
* 也是延迟加载
* @param applicationContext
*/
private static void lookupIfAvailable(AnnotationConfigApplicationContext applicationContext) {
ObjectProvider<PersonHolder> userObjectProvider = applicationContext.getBeanProvider(PersonHolder.class);
PersonHolder personHolder = userObjectProvider.getIfAvailable(PersonHolder::createPersonHolder);
System.out.println("当前 User 对象:" + personHolder);
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(LookUpLazyByNameAnnotation.class);
context.refresh();
lookupIfAvailable(context);
}
除了getIfAvailable, ObjectProvider还提供了getIfUnique方法。
根据类型查找
- 单个Bean
/**
* 通过类型查找
* @param beanFactory
*/
public static void lookUpByType(BeanFactory beanFactory) {
Client bean = beanFactory.getBean(Client.class);
System.out.println(bean);
}
- 集合类型的查找
/**
* 集合查找 ListableBeanFactory 实现了这个接口就可以进行集合查找
* @param beanFactory
*/
public static void lookUpCollectionByType(BeanFactory beanFactory) {
if (beanFactory instanceof ListableBeanFactory) {
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
Map<String, Client> beansOfType = listableBeanFactory.getBeansOfType(Client.class);
System.out.println(beansOfType);
}
}
根据注解查找
- 集合查找
/**
* 集合查找
* @param beanFactory
*/
public static void lookUpCollectionByAnnotation(BeanFactory beanFactory) {
if (beanFactory instanceof ListableBeanFactory) {
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
Map<String, Object> beansOfType = listableBeanFactory.getBeansWithAnnotation(Super.class);
System.out.println(beansOfType);
}
}
依赖查找详细版本
-
单一类型依赖查找(主要是基于BeanFactory)
根据Bean名称查找 -
getBean(String)
-
Spring 2.5 覆盖默认参数:getBean(String, Object)
根据Bean类型查找
Bean实时查找
- Spirng 3.0getBean(Class)
- Spring 4.1覆盖默认参数:getBean(Class, Object)
Spring 5.1 Bean 延迟查找
- getBeanProvider(Class)
- getBeanProvider(ResolvableType)
根据名称 + 类型查找 : getBean(Class, Name)
JNDI - javax.naming.Context#lookup(javax.naming.Name)
JavaBeans-java.beans.beancontext.BeanContext
-
集合类型依赖查找(Listable BeanFactory)
-
根据 Bean 类型查找
- 获取同类型 Bean 名称列表
- getBeanNamesForType(Class)
- Spring 4.2 getBeanNamesForType(ResolvableType)
- 获取同类型 Bean 实例列表
- getBeansOfType(Class)以及重载方法
- 获取同类型 Bean 名称列表
-
通过注解类型查找
Spring 3.0 获取标注类型 Bean 名称列表- getBeanNamesForAnnotation(Class<? extends Annotation>
-
Spring 3.0 获取标注类型 Bean 实例列表
- getBeansWithAnnotation(Class<? extends Annotation>)
-
Spring 3.0 获取指定名称+标注类型 Bean 实例
- findAnnotationOnBean(String, Class<? extends Annotation>)
-
层次性依赖查找接口-HierarchicalBeanFactory
双亲 BeanFactory:getParentBeanFactory()
层次性查找
根据 Bean 名称查找
基于 containsLocalBean 方法实现
根据 Bean 类型查找实例列表
单一类型:BeanFactoryUtils#beanOfType
集合类型:BeanFactoryUtils#beansOfTypelncludingAncestors
根据 Java 注解查找名称列表
BeanFactoryUtils#beanNamesForTypelncludingAncestors
public class Client {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Client.class);
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 创建父亲工厂
BeanFactory parent = createParent();
// 设置父亲工厂
beanFactory.setParentBeanFactory(parent);
// 获取父工厂
HierarchicalBeanFactory parentBeanFactory = (HierarchicalBeanFactory) beanFactory.getParentBeanFactory();
// 父亲工厂查询
disPlayLocalBean(parentBeanFactory, "user");
// 当前工厂查询
disPlayLocalBean(beanFactory, "user");
// 双亲委派 当前工厂查不到 查父亲工厂
displayContainsBean(beanFactory, "user");
context.refresh();
context.close();
}
public static BeanFactory createParent() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("beans.xml");
return beanFactory;
}
public static void displayContainsBean(HierarchicalBeanFactory beanFactory , String beanName) {
boolean containsBean = containsBean(beanFactory, beanName);
System.out.printf("当前工厂是否包含 %s",containsBean);
}
public static boolean containsBean(HierarchicalBeanFactory beanFactory, String beanName) {
BeanFactory parent = beanFactory.getParentBeanFactory();
if (parent instanceof HierarchicalBeanFactory) {
HierarchicalBeanFactory parentHierarchicalBeanFactory = HierarchicalBeanFactory.class.cast(parent);
if (containsBean(parentHierarchicalBeanFactory, beanName)) {
return true;
};
}
return beanFactory.containsBean(beanName);
}
public static void disPlayLocalBean(HierarchicalBeanFactory beanFactory, String beanName) {
System.out.printf("当前工厂是否包含 %s", beanFactory.containsLocalBean(beanName));
System.out.println();
}
}
- 延迟查找
主要涉及 ObjectFactory 和 ObjectProvider
public class Client {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Client.class);
context.refresh();
lookupIfAvailable(context);
context.close();
}
public static void lookupIfAvailable(ApplicationContext context) {
ObjectProvider<User> beanProvider = context.getBeanProvider(User.class);
User user = beanProvider.getIfAvailable(() -> User.createUser());
System.out.println(user);
}
}
- 安全查找
也就是说单一查前两个会抛出异常,所以不安全,其它的方法获取Bean获取不到也不会抛出异常。
public class Client {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Client.class);
context.refresh();
displayBeanFactoryGetBean(context);
}
/**
* 会发生异常
* @param beanFactory
*/
public static void displayBeanFactoryGetBean(BeanFactory beanFactory) {
try {
beanFactory.getBean(User.class);
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 内部依赖
- 依赖查找中的异常
参考资料:Spring核心编程思想。