从Bean的装配理解Spring框架

阅读此文前,可以参考这篇文章:
Spring源码解析


基于XML装配Bean

applicationContext.xml文件


<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
        http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="helloSpring" class="com.gjf.HelloSpring">
    
    
    <property name="who" value="Spring"/>
bean>
beans>
  1. 可以通过ClassPathXmlApplicationContext加载applicationContext.xml文件
public class HelloSpringTest {
     
    @Test
    public void test() {
     
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        HelloSpring helloSpring = (HelloSpring)applicationContext.getBean("helloSpring");
        helloSpring.print();
    }
}
  1. ClassPathXmlApplicationContext源码
	/**
      独立的XML应用程序上下文,从类路径中获取上下文定义文件
      是一个简单的一站式便利ApplicationContext
	 */
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
     
	@Nullable
	private Resource[] configResources;
	/**
     为bean样式的配置创建一个新的ClassPathXmlApplicationContext
	 * @see #setConfigLocation
	 * @see #setConfigLocations
	 * @see #afterPropertiesSet()
	 */
	public ClassPathXmlApplicationContext() {
     
	}

	/**
    创建一个新的ClassPathXmlApplicationContext,
    从给定的XML文件中加载定义,并自动刷新上下文。
	 * @param configLocation resource location
	 * @throws BeansException if context creation failed
	 */
	public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
     
		this(new String[] {
     configLocation}, true, null);
	}

ClassPathXmlApplicationContext的UML关系图,如果读过spring的源码,可能发现很多熟悉的类或者接口;

可以参考这篇文章:Spring源码解析

BeanFactory接口:Spring的IOC容器核心接口,它的职责包括,实例化,有很多的实现类;

ApplicationContext接口:用于访问应用程序组件的Bean工厂方法,以通用方式加载文件资源的能力等

(Spring的上下文,我简单理解就是spring的当前运行的环境,也可以理解是spring可以利用的资源。)

ApplicationContext有两个主要的实现类:ClassPathXmlApplicationContext:默认从类路径加载配置文件,还有FileSystemXmlApplicationContext:默认从文件系统中装载配置文件

从Bean的装配理解Spring框架_第1张图片
理清spring创建定制Bean的整个过程

Bean的装配方式:

  1. 基于XML的装配
  2. 基于注解的装配
  3. 自动装配

    

    

    
  

创建实例对象不在是调用者来创建而是交给spring(控制反转),在Spring框架实例化Bean的过程中,首先调用Bean默认的构造方法来实例化Bean对象,然后通过反射的方式调用setter方法注入属性值(依赖注入)

依赖注入时,要求Bean必须满足下列要求

  1. 提供一个默认的无参构造方法
  2. 需要为注入的属性提供对应的setter方法

基于注解装配Bean

减少xml文件的使用,引入注解

Spring常用的注解

定义bean的注解 说明
@Component 描述spring中的bean
@Repository 用于数据访问层(Dao),标识为spring的bean,功能与@Component相似
@Service 通常用于业务层(Service层),将类标识为spring的bean,功能与@Component相似
@Controller 通常作用于控制层(Controller层),将类标识为spring的bean,功能与@Component相似
  • 找@Repository的源码看看
@Target({
     ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
     

	/**
	该值可能表示建议使用逻辑组件名称,如果是自动检测到的组件,
	则将其转换为Spring bean. 
	 */
	@AliasFor(annotation = Component.class)
	String value() default "";

}
Bean组件装配注解 说明
@Autowired 用于对bean的属性变量,构造方法进行标注,按照默认bean的类型完成自动配置工作
@Resource 用于对bean的属性变量,构造方法进行标注,按照默认bean的实例名称完成自动配置工作
@Qualifier 与@Autowired配合使用,会默认的按bean类型装配修改为按实例名称装配,实例名称由@Qualifier参数指定
//@Autowired事例
@Service("userService")
public class UserServiceImpl implements UserService {
     
    @Autowired  //默认按照类型匹配
    private UserDao userDao;
/*    @Override      使用@Autowired 直接注入属性,可以省略setter方法
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }*/
}
  • 点进@Autowired,AutowiredAnnotationBeanPostProcessor 进去看
 /* @author Juergen Hoeller
 * @author Mark Fisher
 * @author Sam Brannen
 * @since 2.5
 * @see AutowiredAnnotationBeanPostProcessor  //see see看
 * @see Qualifier
 * @see Value
 */
@Target({
     ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
     
	boolean required() default true;

}
/**
为Spring的标准{@link Autowired @Autowired}和
{@link Value @Value}注释创建一个新的{@code AutowiredAnnotationBeanPostProcessor}
还支持JSR-330的{@link javax.inject.Inject @Inject}批注(如果可用)
	 */
	@SuppressWarnings("unchecked")
	public AutowiredAnnotationBeanPostProcessor() {
     
		this.autowiredAnnotationTypes.add(Autowired.class);
		this.autowiredAnnotationTypes.add(Value.class);
		try {
     
			this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
					ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
			logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
		}
		catch (ClassNotFoundException ex) {
     
			// JSR-330 API not available - simply skip.
		}
	}
	/**
	设置“自动装配”注释类型,以用于构造函数,字段,setter方法和任意配置方法。 
	默认的自动装配注释类型是Spring提供的{@link Autowired @Autowired}和{@link Value @Value}注释以及 JSR-330的{@link javax.inject.Inject @Inject}注释, 如果可供使用的话。 * 

存在此setter属性,以便开发人员可以提供自己的*(非特定于Spring的)批注类型,以指示应该自动装配成员。 */ public void setAutowiredAnnotationType(Class<? extends Annotation> autowiredAnnotationType) { Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null"); this.autowiredAnnotationTypes.clear(); this.autowiredAnnotationTypes.add(autowiredAnnotationType); }

发现什么?spring真强大!哈哈哈!

{@link Autowired @Autowired}和{@link Value @Value}注释创建一个新的{@code AutowiredAnnotationBeanPostProcessor},熟悉的:BeanPostProcessor

就讲这些吧,希望可以给初学Spring的猿提供捷径吧
一键三连收藏


你可能感兴趣的:(Spring,新星计划,spring,java)