天天看點

01 Spring IoC 依賴查找

1、根據Bean名稱查找

(1)建立執行個體類

package org.binsoft.thinking.in.spring.ioc.overview.domain;

/**
 * TODO
 *
 * @author Administrator
 * @version 1.0
 * @date 2021/1/1 12:05
 */
public class User {

    private Long id;
    private String name;


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
           

(2)在類路徑下的resources建立目錄 META-INF,并建立spring的xml配置檔案

01 Spring IoC 依賴查找
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="org.binsoft.thinking.in.spring.ioc.overview.domain.User">
        <property name="id" value="1"/>
        <property name="name" value="彬少"/>
    </bean>
</beans>
           

(3)根據名稱實時查找

beanFactory.getBean

package org.binsoft.thinking.in.spring.ioc.overview.dependency.lookup;

import org.binsoft.thinking.in.spring.ioc.overview.annotation.Super;
import org.binsoft.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Map;

/**
 * 依賴查找執行個體
 * 1. 通過名稱的方式來查找
 *
 * @author binsoft
 * @version 1.0
 * @date 2021/1/1 11:53
 */
public class DependencyLookupDemo {
    public static void main(String[] args) {
        // 配置 XML 配置檔案
        // 啟動 Spring 應用上下文
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup-context.xml");
        lookupInRealTime(beanFactory);

    }

    private static void lookupInRealTime(BeanFactory beanFactory) {
        User user = (User) beanFactory.getBean("user");
        System.out.println("實時查找:" + user);
    }
}
           

(4)根據名稱延遲查找

主要通過ObjectFactory接口實作:

01 Spring IoC 依賴查找

主要實作的FactoryBean為:

org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean

通過源碼分析,此類有兩個重要的地方:

  • 目标Bean名稱,需要外部進行配置指定
@Nullable
	private String targetBeanName;
           

實作ObjectFactory接口的私有靜态内部類TargetBeanObjectFactory,代理BeanFactory來進行Bean執行個體的查找:

/**
 * Independent inner class - for serialization purposes.
 */
@SuppressWarnings("serial")
private static class TargetBeanObjectFactory implements ObjectFactory<Object>, Serializable {

   private final BeanFactory beanFactory;

   private final String targetBeanName;

   public TargetBeanObjectFactory(BeanFactory beanFactory, String targetBeanName) {
      this.beanFactory = beanFactory;
      this.targetBeanName = targetBeanName;
   }

   @Override
   public Object getObject() throws BeansException {
      return this.beanFactory.getBean(this.targetBeanName);
   }
}
           

在配置檔案中,對ObjectFactoryCreatingFactoryBean進行配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="org.binsoft.thinking.in.spring.ioc.overview.domain.User">
        <property name="id" value="1"/>
        <property name="name" value="彬少"/>
    </bean>

    <bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
        <property name="targetBeanName" value="user"/>
    </bean>

</beans>
           

通過ObjectFactory的 T getObject() throws BeansException; 方法來查找Bean執行個體。

package org.binsoft.thinking.in.spring.ioc.overview.dependency.lookup;

import org.binsoft.thinking.in.spring.ioc.overview.annotation.Super;
import org.binsoft.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Map;

/**
 * 依賴查找執行個體
 * 1. 通過名稱的方式來查找
 *
 * @author binsoft
 * @version 1.0
 * @date 2021/1/1 11:53
 */
public class DependencyLookupDemo {
    public static void main(String[] args) {
        // 配置 XML 配置檔案
        // 啟動 Spring 應用上下文
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup-context.xml");
        lookupInLazy(beanFactory);
    }

    private static void lookupInLazy(BeanFactory beanFactory) {
        ObjectFactory<User> objectFactory = (ObjectFactory<User>) beanFactory.getBean("objectFactory");
        User user = objectFactory.getObject();
        System.out.println("延遲查找:" + user);
    }


}
           

從此過程中,可以看出, ObjectFactory 對象并不是直接傳回了實際的Bean,而是一個Bean的查找代理。當得到ObjectFactory對象時,相當于Bean沒有被建立,隻有當調用getObject()方法時,才會觸發Bean執行個體化等生命周期 。

2、根據Bean類型查找

(1)單個Bean對象

主要通過BeanFactory的

<T> T getBean(Class<T> requiredType) throws BeansException;

方法來實作,因為涉及到泛型,是以要求Spring的版本為3.0及以上:

01 Spring IoC 依賴查找

并通過注釋,可以看出,需要利用ListableBeanFactory:

package org.binsoft.thinking.in.spring.ioc.overview.dependency.lookup;

import org.binsoft.thinking.in.spring.ioc.overview.annotation.Super;
import org.binsoft.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Map;

/**
 * 依賴查找執行個體
 * 1. 通過名稱的方式來查找
 *
 * @author binsoft
 * @version 1.0
 * @date 2021/1/1 11:53
 */
public class DependencyLookupDemo {
    public static void main(String[] args) {
        // 配置 XML 配置檔案
        // 啟動 Spring 應用上下文
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup-context.xml");
        //按照類型查找
        lookupByType(beanFactory);
    }

    private static void lookupByType(BeanFactory beanFactory) {
        User user = beanFactory.getBean(User.class);
        System.out.println("實時查找:" + user);
    }

}
           

(2)集合Bean對象

主要通過ListableBeanFactory接口的

<T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException;

方法

01 Spring IoC 依賴查找
package org.binsoft.thinking.in.spring.ioc.overview.dependency.lookup;

import org.binsoft.thinking.in.spring.ioc.overview.annotation.Super;
import org.binsoft.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Map;

/**
 * 依賴查找執行個體
 * 1. 通過名稱的方式來查找
 *
 * @author binsoft
 * @version 1.0
 * @date 2021/1/1 11:53
 */
public class DependencyLookupDemo {
    public static void main(String[] args) {
        // 配置 XML 配置檔案
        // 啟動 Spring 應用上下文
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup-context.xml");
        //按照類型查找集合對象
        lookupCollectionByType(beanFactory);
    }

    private static void lookupCollectionByType(BeanFactory beanFactory) {
        if (beanFactory instanceof ListableBeanFactory) {
            ListableBeanFactory listableBeanfactory = (ListableBeanFactory) beanFactory;
            Map<String, User> users = listableBeanfactory.getBeansOfType(User.class);
            System.out.println("查找到的所有的 User 集合對象:" + users);
        }
    }



}
           

3、根據Bean名稱+類型查找

主要通過BeanFactory接口的

<T> T getBean(String name, Class<T> requiredType) throws BeansException;

方法來實作,最主要的一點是,此方法會進行一定程度的類型安全檢查:會抛出異常:BeanNotOfRequiredTypeException

01 Spring IoC 依賴查找

4、根據Java注解查找

主要通過ListableBeanFactory接口的

Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;

方法來實作:

01 Spring IoC 依賴查找

(1)建立一個注解Super

package org.binsoft.thinking.in.spring.ioc.overview.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Super {
}
           

(2)建立SuperUser對象并繼承自User,并為Super對象标注注解@Super

package org.binsoft.thinking.in.spring.ioc.overview.domain;

import org.binsoft.thinking.in.spring.ioc.overview.annotation.Super;

/**
 * TODO
 *
 * @author Administrator
 * @version 1.0
 * @date 2021/1/1 13:14
 */

@Super
public class SuperUser extends User {

    private String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "SuperUser{" +
                "address='" + address + '\'' +
                "} " + super.toString();
    }
}
           

(3)通過Spring XML檔案配置Super對象,并指定屬性:parent="user"和 primary="true"

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="org.binsoft.thinking.in.spring.ioc.overview.domain.User">
        <property name="id" value="1"/>
        <property name="name" value="彬少"/>
    </bean>

    <bean id="superUser" class="org.binsoft.thinking.in.spring.ioc.overview.domain.SuperUser" parent="user"
          primary="true">
        <property name="address" value="北京"/>
    </bean>

    <bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
        <property name="targetBeanName" value="user"/>
    </bean>

</beans>
           
01 Spring IoC 依賴查找

(4)通過getBeansWithAnnotation方法類查找:

package org.binsoft.thinking.in.spring.ioc.overview.dependency.lookup;

import org.binsoft.thinking.in.spring.ioc.overview.annotation.Super;
import org.binsoft.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Map;

/**
 * 依賴查找執行個體
 * 1. 通過名稱的方式來查找
 *
 * @author binsoft
 * @version 1.0
 * @date 2021/1/1 11:53
 */
public class DependencyLookupDemo {
    public static void main(String[] args) {
        // 配置 XML 配置檔案
        // 啟動 Spring 應用上下文
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup-context.xml");
        //按照注解查找
        lookupByAnnotationType(beanFactory);
    }

    private static void lookupByAnnotationType(BeanFactory beanFactory) {
        if (beanFactory instanceof ListableBeanFactory) {
            ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
            Map<String, Object> users = listableBeanFactory.getBeansWithAnnotation(Super.class);
            System.out.println("查找标注 @Super 的所有User集合對象:" + users);

        }
    }


}