Spring原理分析(仿照spring源码写装配bean和依赖注入)

一、环境准备

新建maven项目,配置maven依赖

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.miller.spring</groupId>
  <artifactId>spring-practice</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>spring-practice Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <!-- maven编译属性 -->
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <!-- maven依赖配置,spring4.3依赖包 -->
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.3.20.RELEASE</version>
    </dependency>
  </dependencies>
</project>

二、目录结构

在这里插入图片描述

三、关于Spring容器启动:

(1)、基于spring4的注解方式

代码:

@Configuration //声明此类是配置类
@ComponentScan("com.base")
public class App {

	public static void main(String[] args) {
	 	//传入配置类
		AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(App.class); 
		//传入包名,扫描此包下所以的类,有标注就被spring容器管控。
		AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext("com.base");  
		
	}
}

理解:

1、通过AnnotationConfigApplicationContext对象的构造方法,启动Spring容器,并且返回一个Spring容器上下问对象context
2、有三种方式启动Spring容器,
   (1):new AnnotationConfigApplicationContext(App.class);  传入被标注@Configuration的类(也就是配置类)
   (2):new AnnotationConfigApplicationContext("com.base");   传入包路径,自动扫描包下的所有类
   (3):@ComponentScan("com.base")  直接适用@ComponentScan注解扫描

四、关于Spring的Bean的装配:

将Bean装配到spring容器有以下几种方式:

(1)、直接在配置类里面new一个对象,装配到容器

@Bean(initMethod = "show") //装配对象到spring容器,并且设置自定义的初始化方法 show
@Scope("prototype") //多例模式(每次请求创建一个新对象)
public User createUser(){
    return new User();
}

 @Bean(initMethod = "show") //装配对象到spring容器,并且设置自定义的初始化方法 show
 @Scope("prototype") //多例模式(每次请求创建一个新对象)
 @Primary  //当spring容器有两个相同类型的bean时,再按照bean类型获取就会报错,所以这里指定获取时就获取当前标注的这个bean
 public User createUser2(){
        return new User();
 }

(2)、通过beanFactory接口来实现装配bean

代码:
RunableFactoryBean.class:

public class RunableFactoryBean implements FactoryBean<Runable> {
    @Override
    public Runable getObject() throws Exception {
        return new Runable();
    }

    @Override
    public Class<?> getObjectType() {
        return Runable.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

APP.class:

@Bean //装配工厂bean,这个工厂bean会返回一个Runable对象装配到spring容器里面
public RunableFactoryBean createRunableFactoryBean(){
    return new RunableFactoryBean();
}

理解:

工厂bean实现FactoryBean接口方法:
getObject是返回bean、getObjectType是返回bean类型、isSingleton是判断是否单例
然后在配置类装配这个工厂bean,这样就实现了bean的装配。

(3)、通过spring4.3的新特性来实现装配bean

代码:

CarFactoryBean.class

public class CarFactoryBean {
   public Car createCar(){
       return new Car();
   }
}

APP.class:

@Bean //装配CarFactoryBean工厂bean
public CarFactoryBean createCarFactoryBean(){
    return new CarFactoryBean();
}
@Bean //因为上面已经把CarFactoryBean装配到spring容器了,所以参数是直接拿的spring容器里面的CarFactoryBean
public Car createCar(CarFactoryBean carFactoryBean){
   //spring4.3的新特性,当spring容器中需要某个bean时,只要spring容器里面有,就可以直接拿来用
   return carFactoryBean.createCar(); 
}

理解:

先装配一个工厂bean,这个工厂bean返回一个Car对象,然后在配置声明装配方法
,此方法是参数是工厂bean(carFactoryBean),
Spring的新特性,当spring容器中需要某个bean时,
只要spring容器里面有,就可以直接拿来用,所以createCar方法的参数carFactoryBean就是最开始装配的工厂bean

五、关于Spring的Bean的依赖注入
以下几种方式
(1)、通过@Autowired注解注入

@Autowired //注入User类型的bean
private User user;

(2)、实现了ApplicationContextAware接口,通过setApplicationContext方法注入

代码:

AutoAwarUser.class

@Component  //通过实现ApplicationContextAware接口实现依赖注入
public class AutoAwarUser implements ApplicationContextAware {

    private User user;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException{
        this.user=applicationContext.getBean(User.class);
	}

    public void show(){
        System.out.println("AutoAwarUser show:"+user);
    }
}

App.class:

//AutoAwarUser实现了ApplicationContextAware接口,通过setApplicationContext方法注入了User对象
  context.getBean("autoAwarUser",AutoAwarUser.class).show();

理解:

实现ApplicationContextAware接口,在接口方法里面,
通过applicationContext对象获取Spring容器里面的User,
 将User注入到属性,完成依赖注入
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值