自动装配:Spring利用依赖注入,完成对IOC容器中的各个组件的依赖关系赋值


[email protected]

1)、默认优先按照类型去容器中找对应的组件---->ioc.getBean(BookDao.class);,如果找到了就赋值

2)、如果找到了多个相同类型的组件,再讲属性的名称作为组件的id去查找--->ioc.getBean("bookDao");

3)、使用@Qualifier("bookDao")来明确指定需要装配的组件的id,而不是使用属性名作为id

4)、自动装配默认的是一定要在容器中找到组件,如果容器中没有就会报错

                 可以设置required = false,是其不必须在容器中找到组件,找不到就是null

@Autowired(required = false)

5)、容器中有多个相同类型的组件,还可以使用@Primary设置每次装配首选的是这个bean,和@Qualifier一起使用 ,还是会自动装配@Qualifier明确指定的bean

给BookService自动注入BookDao 

@Service
public class BookService {
    @Qualifier("bookDao")
    @Autowired
    private BookDao bookDao;

    public BookDao getBookDao() {
        return bookDao;
    }

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    @Override
    public String toString() {
        return "BookService{" +
                "bookDao=" + bookDao +
                '}';
    }
}

测试结果:

自动装配

BookService里的BookDao自动装配成功


2.Spring还支持@Resource(JSR250)和@Inject(JSR330),java规范的注解

[email protected]:可以和@Autowired一样实现自动装配功能,没有@Primary,也没有required属性

[email protected]:使用需要导入javax.inject包,和@Autowired一样实现自动装配功能,支持@Primary,没有required属性


[email protected]的其他用法

@Autowired:不仅可以也在属性上,还能标注在方法上、构造器上、参数上

①、标注在方法上测试

@Bean+方法参数:参数从容器中获取(@Autowired 可以省略)

    @Bean
    public Boss boss(@Autowired Car car){
        return new Boss();
    }

在setCar方法上标注@Autowired:

@Component
public class Boss {

    private Car car;

    public Car getCar() {
        return car;
    }

    /*
    * 将Autowired标注在方法上
    * Spring容器创建对象就会调用这个方法完成赋值
    * 方法使用的自定义的值从ioc容器中获取
    * */
    @Autowired
    public void setCar(Car car) {
        this.car = car;
    }

    @Override
    public String toString() {
        return "Boss{" +
                "car=" + car +
                '}';
    }
}

测试结果:

自动装配


②、构造器

默认加在容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值

如果组件只有一个有参构造器,那么有参构造器的Autowired可以省略


@Autowired标注在Boss的有参构造器上:

@Component
public class Boss {

    private Car car;


    //构造器要用的组件都是从ioc容器中获取
    @Autowired
    public Boss(Car car) {
        this.car = car;
        System.out.println("Boss的有参构造器。。。。");
    }

    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }

    @Override
    public String toString() {
        return "Boss{" +
                "car=" + car +
                '}';
    }
}

测试结果: 

自动装配

③、参数上

标注在参数上效果一样,不多测试


4.自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,.....)

自定义组件实现xxxAware接口:在创建对象的时候,会调用接口规定的方法注入相关组件

自动装配


例子:实现了ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware三个Aware接口

@Component
public class Red implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
    private ApplicationContext applicationContext;

    //获取ioc容器
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        System.out.println("传入的IOC: "+applicationContext);
    }

    //获取bean名字
    public void setBeanName(String name) {
        System.out.println("当前Bean的名字: "+name);
    }

    //
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        String s = resolver.resolveStringValue("你好${os.name} 我是#{2*4}");
        System.out.println("解析的字符串:"+s);
    }
}

在容器创建Red对象时调用Aware的方法

结果:

自动装配


Aware的原理

Debug运行:

自动装配

查看方法调用栈的信息:

自动装配

先调用了postProcessBeforeInitialization(final Object bean, String beanName)方法,

在方法里调用了

自动装配

invokeAwareInterfaces方法:

	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

判断当前的bean是否实现了这些接口,如果实现了就调用该接口的方法 ,传入组件

相关文章:

  • 2021-12-23
  • 2021-06-03
  • 2021-07-22
  • 2022-12-23
猜你喜欢
  • 2022-01-06
  • 2021-09-26
  • 2021-08-18
  • 2021-04-13
  • 2021-11-17
  • 2021-09-03
  • 2021-08-08
相关资源
相似解决方案