如何自定义@autowired注解?

如何自定义@autowired注解?

 

 在上一章节,我们分享了@Autowire注解方式的原理以及源码,对 AutowiredAnnotationBeanPostProcessor这个类的核心方法做了深入分析,本章将对自定义属性注入进行详细分析。

首先我们还是看到这个类AutowiredAnnotationBeanPostProcessor:

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.    }  }

可以看到AutowiredAnnotationBeanPostProcessor的默认构造器做了一件事情,就是这里this.autowiredAnnotationTypes.add(Autowired.class);我们可以很直观的看到Autowired,没错这里就是我们的注解类,如果不行的话我们再看看这个集合autowiredAnnotationTypes

可以看到这里的autowiredAnnotationTypes装的是注解类型,因此可以断定这就是存放我们定义的注解信息,好了,话题先到这里,等会我们再深度分析,下面我们就开始如何基于Spring自定义依赖注入注解,这里一共有两种方式,第一种就十分简单,我们可以直接在注解上加上@Autowired注解,我们看下面个例子:

首先创建一个注解类名MyAutowired

package com;import org.springframework.beans.factory.annotation.Autowired;import java.lang.annotation.*;/** * @author 七天0 * @date 2020/12/16 0016 22:58 * 概要 : */@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Autowiredpublic @interface MyAutowired {}

然后在创建一个User1类和一个User2类

package com;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Lookup;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;@Componentpublic class User2 implements User{  @MyAutowired  private User user1;  @PostConstruct  public void postConstruct(){    System.out.println(user1);  }}
package com;import org.springframework.stereotype.Component;@Componentpublic class User1 implements User {}

代码很简单就不做解释了,然后我们开始写配置类和测试类

import com.MyImportBeanDefinitionRegistrar;import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;import org.springframework.context.annotation.*;@Configuration@ComponentScan("com")/*@EnableAspectJAutoProxy*//*@Import(MyImportBeanDefinitionRegistrar.class)*/public class AppConfig {  }
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Test {    public static void main(String[] args) {      AnnotationConfigApplicationContext annotationConfigApplicationContext=          new AnnotationConfigApplicationContext(AppConfig.class);    }}

注意User2类里面的user1属性,我们可以很清楚的看到我用的是自定义注解 @MyAutowired,然后我们测试一下

Connected to the target VM, address: '127.0.0.1:54489', transport: 'socket'com.User1@549949beDisconnected from the target VM, address: '127.0.0.1:54489', transport: 'socket'Process finished with exit code 0

这里打印了User1,说明我们注入成功了,那么也就是说这样就可以自定义我们的属性注入注解,当然这里虽然简单但是太过于死板,于是我们用第二种方式。

我们还是用案例来解释,首先修改一下我们的注解类

package com;import org.springframework.beans.factory.annotation.Autowired;import java.lang.annotation.*;/** * @author 七天0 * @date 2020/12/16 0016 22:58 * 概要 : */@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface MyAutowired {}

取消@Autowired注解,然后我们再更新下我们的配置类

import com.MyAutowired;import com.MyImportBeanDefinitionRegistrar;import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;import org.springframework.context.annotation.*;import java.lang.annotation.Annotation;import java.util.LinkedHashSet;import java.util.Set;import static java.util.Arrays.asList;import static org.springframework.context.annotation.AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME;@Configuration@ComponentScan("com")/*@EnableAspectJAutoProxy*//*@Import(MyImportBeanDefinitionRegistrar.class)*/public class AppConfig {  //AutowiredAnnotationBeanPostProcessor  @Bean(name = AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)  public AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor(){    AutowiredAnnotationBeanPostProcessor beanPostProcessor=        new AutowiredAnnotationBeanPostProcessor();    Set<Class<? extends Annotation>> autowiredAnnotationTypes        =new LinkedHashSet<>(asList(MyAutowired.class));    beanPostProcessor.setAutowiredAnnotationTypes(autowiredAnnotationTypes);    return beanPostProcessor;  }}

然后在更新下我们的User类

package com;import org.springframework.stereotype.Component;@Componentpublic class User1 implements User {}
package com;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Lookup;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;@Componentpublic class User2 implements User{  @MyAutowired  private User user1;  @Autowired  private User user2;  @PostConstruct  public void postConstruct(){    System.out.println(user1);    System.out.println(user2);  }}

这里的User2类我们用了@Autowired和 @MyAutowired,然后我们在测试下我们的代码

public class Test {    public static void main(String[] args) {      AnnotationConfigApplicationContext annotationConfigApplicationContext=          new AnnotationConfigApplicationContext(AppConfig.class);    }}

测试结果如下

com.User1@22f59fanullProcess finished with exit code 0

可以看到我们的user2注入失败了,而我们的自定义类成为了自动注入得类,这是为什么?原因就在我们的AppConfig类里面,请大家注意这行代码beanPostProcessor.setAutowiredAnnotationTypes(autowiredAnnotationTypes);我们看下图

可以看到这里Spring会清空原有的东西,然后再进行添加,因此这也是为什么Spring自己的@Autowired会失效,是不是突然觉得Spring的设计有那么点牛逼,哈哈,这里再提出一个问题,我们的name = AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME为什么一定要是它,如果不是它,效果会一样吗?为什么?这里读者可以尝试一下,然后自行自考,最后笔者做一点提示,注意Spring内部创建的默认AutowiredAnnotationBeanPostProcessor的BeanName是什么,好了本章内容分享到这里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值