4、属性赋值和自动装配

一、属性赋值

  • 属性赋值相关的注解

@Value
@PropertySource
springboot中的@ConfigurationProperties(prefix = "xxx")

二、自动装配

  • 概念:Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值

1、@Autowired:自动注入

1)、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值
2)、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找applicationContext.getBean("bookDao")
3)、@Qualifier("bookDao"):使用@Qualifier指定需要装配的组件的id,而不是使用属性名
4)、自动装配默认一定要将属性赋值好,没有就会报错;可以使用@Autowired(required=false);
5)、@Primary:让Spring进行自动装配的时候,默认使用首选的bean;也可以继续使用@Qualifier指定需要装配的bean的名字

2、@Resource(JSR250)和@Inject(JSR330)[java规范的注解]

1、@Resource:可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;没有能支持@Primary功能。
2、@Inject:需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;

总结:

  • @Autowired:Spring定义的; @Resource、@Inject都是java规范
  • AutowiredAnnotationBeanPostProcessor解析完成自动装配功能

三、自定义组件想要使用Spring容器底层的一些组件

  • 例如:ApplicationContext,BeanFactory,xxx

1、Aware接口

  • Aware是一个具有标识作用的超级接口,实现该接口的bean是具有被spring 容器通知的能力的,而被通知的方式就是通过回调。总之:直接或间接实现了这个接口的类,都具有被spring容器通知的能力。
  • 继承接口:


    4、属性赋值和自动装配_第1张图片
    Aware接口继承接口
  • 可以知道这些xxxAware接口都只有一个setxxx方法,目的就是给实现该接口的类的xxx属性设置值。在spring中这些实现xxxAware接口的类是如何实现感应并设置xxx属性的值的呢,答案就是在spring容器中在工厂类创建实例后使用instanceof判断实例是否属于xxxAware接口的实例,如果结果是true的话,那么spring容器类就会调用实例的setXxx()方法给实例的xxx属性设置值。简单来说就是实现这些 Aware接口的Bean在被初始之后,可以从Spring容器中取得一些相对应的资源,例如实现BeanFactoryAware接口的Bean在初始后,Spring容器将会注入BeanFactory的实例,而实现ApplicationContextAware接口的Bean,在Bean被初始后,将会被注入 ApplicationContext的实例等等。
  • 注意:

有六大类xxxAware是由spring容器自动注册在容器中的,应用程序不需要再次的在容器中注入了,但是如果我们实现其他的xxxAware,还必须在容器中注入才能使用,从ApplicationContextAwareProcessor源码可以解读出,这六类特殊的xxxAware是:

  • @see org.springframework.context.EnvironmentAware
  • @see org.springframework.context.EmbeddedValueResolverAware
  • @see org.springframework.context.ResourceLoaderAware
  • @see org.springframework.context.ApplicationEventPublisherAware
  • @see org.springframework.context.MessageSourceAware
  • @see org.springframework.context.ApplicationContextAware

2、从实现到原理再到实现

  • 前面可知实现xxxAware接口主要是为了获取spring的一些特性
    (1)自己实现一个接口获取spring的特性,比如BeanFactoryAware
public class Animal implements BeanFactoryAware {
    private BeanFactory beanFactory;
 
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
}
  • 注意:我们的Animal 类实现了aware接口,如果我们直接在应用中new一个Animal 的对象,当然是拿不到beanFactory变量的,我们必须在spring的配置文件中声明我们的fruit对象才行,也就是说Animal 对象必须交给容器进行管理,容器帮你把各种aware接口中想要注入的对象设置到bean中。具体看容器管理aware接口的代码实现,代码在AbstractAutowireCapableBeanFactory的initializeBean方法中:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction() {
                @Override
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }
// 开始Bean初始化前处理、初始化、初始化后处理
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }
 
 

可以看出来,aware接口的各种处理是在属性设置完成之后、bean初始化之前完成的。显然的,如果我们直接new出来一个bean,这些框架性的特性是没有使用到的。但是上面提到的六中特殊的xxxAware,比如ApplicationContextAware,可以完成自动化在容器中进行接口注入,原来在应用中创建上下文容器时会注册一个BeanPostProcessor------ApplicationContextAwareProcessor,在这个类里面进行了context的注入,这样我们就能能够拿到bean中的context对象:

public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;

        if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                        bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                        bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged(new PrivilegedAction() {
                @Override
                public Object run() {
                    invokeAwareInterfaces(bean);
                    return null;
                }
            }, acc);
        }
        else {
            invokeAwareInterfaces(bean);
        }

        return bean;
    }
 
 

然后在AbstractApplicationContext.prepareBeanFactory方法中,进行对ApplicationContextAwareProcessor的注入。

    // Configure the bean factory with context callbacks.
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

3、自定义aware接口实现

  • 知道原理后我们要实现自定义aware接口实现,需要完成下面两个步骤:
    1.实现我们aware接口的postprocessor,并在容器中注册;
    2.bean实体类集成我们自定义的aware接口并实现
  • 具体案例实现:
    (1)自定义aware接口:
public interface AppleAware {
    void setApple(Apple a);
}

(2)自定义Processor实现BeanPostProcessor接口

public class AppleAwarePostProcessor implements BeanPostProcessor {
 
    private Apple a;
 
    public AppleAwarePostProcessor(Apple a) {
        this.a = a;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof AppleAware) {
            ((AppleAware) bean).setApple(a);
        }
        return bean;
    }
 
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // TODO Auto-generated method stub
        return bean;
    }
 
}

(3)实现AppleAware 接口完成自定义bean注入

public class Market implements AppleAware {
 
    private Apple a;
 
    @Override
    public void setApple(Apple a) {
         this.a = a;
    }
 
    public String getName() {
        return a.getName();
    }
 
}

(4)测试

  • 一定要把我们的BeanPostProcessor加入到当前容器中,这一点非常重要
public class TestAware {
    public static void main(String args[]) {
        ConfigurableBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
        BeanPostProcessor bpp = new AppleAwarePostProcessor((Apple)beanFactory.getBean("apple"));
    // 工厂对象中加入我们自定义的BeanPostProcessor
        beanFactory.addBeanPostProcessor(bpp);
        Market market = (Market) beanFactory.getBean("market");
        System.out.println(market.getName());
    }
}

参考:
https://www.cnblogs.com/RunForLove/p/5828916.html

你可能感兴趣的:(4、属性赋值和自动装配)