• Autowired使用说明


    使用了那么久Spring,一下子问我Autowired注解使用条件,答不上来吧,看了Spring源码,一点点收货;

     废话少说,要是Autowired生效,需要注册BeanPostProcessor,你说我没注册也能用啊,那你一定用了<context:annotation-config>或者<context:component-scan base-package="扫描包名/>这两个注解吧;

    简单的测试代码(两个类 Person  以及 Pet  ,一个Person类持有一个Pet类的关系)

      Person类:

    package com.lvbinbin.autowired;
    import org.springframework.beans.factory.annotation.Autowired;
    public class Person {
        private String name;
        
        @Autowired
        private Pet pet;
    
        public String toString() {
            return "Person name:" + name + ",Pet:" + pet;
        }
    
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }

        Pet类:

    package com.lvbinbin.autowired;
    public class Pet {
        private String name;
    
        public String toString() {
            return "Pet name:"+name;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }

      Spring的配置文件(将Person以及Pet放到Spring容器里,或者通过包扫描加入容器)

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
     6         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
     7 
     8 <bean id="person1" class="com.lvbinbin.autowired.Person">
     9     <property name="name" value="lvbinbin"></property>
    10 </bean>
    11 
    12 <bean id="pet1" class="com.lvbinbin.autowired.Pet">
    13     <property name="name" value="xiaobinggan"/>
    14 </bean>
    15 </beans>

    简单写个类测试一下:

     1 package com.lvbinbin.autowired;
     2 
     3 import org.springframework.context.support.ClassPathXmlApplicationContext;
     4 
     5 public class TestCases {
     6 
     7     public static void main(String[] args) {
     8         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("com/lvbinbin/autowired/spring.xml");
     9         Person p1=(Person) context.getBean("person1");
    10         System.out.println(p1);
    11     }
    12 }

       以上代码,测试发现没有注入Pet属性; 也说明了 XML文件 property注入属性需要有对应的Setter  Getter方法;

      在Spring配置文件中加入下面几句话之一,Autowired就可以生效:   <bean id="aabp" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

                                或者 <context:annotation-config/> 

                                或者 <context:component-scan base-package="包路径"/>  

    其中包路径随意写也能使用Autowired注解生效,但是不建议写无意义的路径;

     额外注意几点:  1. Autowired注解只有一个属性  required  可选值 false / true :  默认为true ,如果实例化该属性时候,IOC容器即BeanFactory中没有可以注入的,抛出异常 ;

                                       设置为false ,实例化该属性时候 容器里没有该类型的bean 同样可以运行 ;

                              2.Autowired注解的属性可以有setter  getter方法;底层是通过反射设置上的值,setter getter方法需不需要都可以成功 ;

                              3.Autowired注解可以标注在属性、或者方法上, 但是属性和方法都不允许为 static 类型;

            4.Autowired注解可以注入一些Spring默认配置上的,ApplicationContext、BeanFactory、Enviroment等等对象;

            5.Autowired注解标注在方法上时,方法入参需要都在SpringIOC容器中存在,该类型对象有一个不存在就会抛出异常

    偷懒给Person类添加一些public属性;

    测试main方法如下:

     1 public static void main(String[] args) {
     2         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("com/lvbinbin/autowired/spring.xml");
     3         Person p1=(Person) context.getBean("person1");
     4         System.out.println(p1);
     5         System.out.println("ac:"+p1.ac);
     6         System.out.println("bf:"+p1.bf);
     7         System.out.println("rl:"+p1.rl);
     8         System.out.println("ap:"+p1.ap);
     9         System.out.println("env:"+p1.env);
    10     }

    查看下输出:其实ResourceLoader、ApplicationEventPublisher都是ApplicationContext的具体对象,因为ApplicationContext实现了这些接口;

    博客的最后,记录一个笨比的尝试:(下面的例子是Spring源码编译后改动,编译教程建议看Spring源码深度解析)

    Autowired注解可以标注在 方法入参上,测试一下:

    上例Person类简单改造下:注释掉 Pet属性上的Autowired,在方法入参中加上@Autowired;这里补充下:Autowired的注解的方法名不一定非要set这种形式的方法;

    1     // @Autowired
    2     private Pet pet;
    3     
    4     public void test1(@Autowired Pet p) {
    5         this.pet=p;
    6     }

    同样的测试用例:发现Pet属性并没有注入上去(如果可以注入上去望指教);

     简单改造下,可以支持 单个参数的Autowired注入,多个参数的Autowired实现,我力有不逮;

    AutowiredAnnotationBeanPostProcessor的 findAutowiredAnnotation方法简单改造下,如果入参是Method且没有注解标注,顺便检查下参数上是否有Autowired注解,没有再返回null,就可以简单实现单个参数上的Autowired功能吧

     1       @Nullable
     2     private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
     3         if (ao.getAnnotations().length > 0) {  // autowiring annotations have to be local
     4             for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
     5                 AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
     6                 if (attributes != null) {
     7                     return attributes;
     8                 }
     9             }
    10         }
            return null;
    11 }

    改造添加几行代码后方法这样的:

     1 @Nullable
     2     private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
     3         if (ao.getAnnotations().length > 0) {  // autowiring annotations have to be local
     4             for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
     5                 AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
     6                 if (attributes != null) {
     7                     return attributes;
     8                 }
     9             }
    10         }
    11         if(ao instanceof Method) {
    12             Parameter[] parameters = ((Method) ao).getParameters();
    13             for (Parameter parameter : parameters) {
    14                 for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
    15                     AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(parameter, type);
    16                     if (attributes != null) {
    17                         return attributes;
    18                     }
    19                 }
    20             }      
    21         }
    22         return null;
    23     }

    同样的我们再测试下:发现已经可以实现了Autowired单个属性的注入,多个属性的改造量太大,可以(wo)但(bu)没必要(hui);

                

  • 相关阅读:
    盘符格式转换成NTFS格式
    jdk环境变量配置
    修改mysql密码
    端口占用解决
    程序执行原理
    第一个Python程序
    pip安装第三方库失败的问题
    windows本地安装mongoDB并且安装可视化工具studio 3t
    开发时前端测试方法
    虚拟机配置vimrc
  • 原文地址:https://www.cnblogs.com/lvbinbin2yujie/p/10073314.html
Copyright © 2020-2023  润新知