• spring(一):spring IoC的注入方式总结


    前言:谈谈对springIOc的理解,两张图很好的阐述了springIoc容器的作用。

          

                传统应用程序示意图.jpg

           

             

                IoC容器后程序结构示意图.jpg

     


     

     

        springIoC容器注入方式有set注入,构造器注入,注解注入。

    一:set方式注入

    1.先准备几个bean类,一个普通的学生类,以及一个A类,A类组合了学生类对象。

    Student.java

    package com.cnblogs.bean;
    
    public class Student {
        // 学号    
        private String sNo;
        private String name;
        private int age;
        // 性别    
        private String sex;
        //年级
        private String grade;
        
        public Student() {
            super();
        }
        public Student(String sNo, String name, int age, String sex, String grade) {
            super();
            this.sNo = sNo;
            this.name = name;
            this.age = age;
            this.sex = sex;
            this.grade = grade;
        }
    
      // set和get方法
      
      // toString方法()
    }

     

    A.java

    package com.cnblogs.bean;
    
    public class A {
        private String desc;
        private Student stu;
        public A() {
            super();
            // TODO Auto-generated constructor stub
        }
        public A(String desc, Student stu) {
            super();
            this.desc = desc;
            this.stu = stu;
        }
        // set和get方法
      
      // toString方法()
    }

     set.xml中

      <!-- 基于set方法的注入 -->
        <bean name="stu" class="com.cnblogs.bean.Student">
            <property name="sNo" value="1001"></property>
            <property name="name" value="jack"></property>
            <property name="age" value="12"></property>
            <property name="sex" value="male"></property>
            <property name="grade" value="三年级"></property>
        </bean>
        <!-- 注入引用类型 -->
        <bean name="A" class="com.cnblogs.bean.A">
            <property name="desc" value="A组合了Student类对象"></property>
            <!-- ref属性表示调用这个setStudent方法的时候要用的参数是名字为stu的对象 -->
            <property name="stu" ref="stu"></property>
        </bean>

    1.<bean>标签中,name和id起标识这个对象的作用,id会帮我们检查给对象起的名字是否规范(名字不能重复,不能有空格,不能已数字开头),name不会检查这些东西。

    class属性是一个类的全限定名,标识配置那个类。

    2.springIoC默认是已单例模式管理对象,即通过相同的名字多次拿出来的对象一样,可以再<bean>标签中加属性 scope="prototype"代表非单例,

    scope="Singleton"代表单例模式。

    3.可以给某一个对象加别名,在</bean>后面加一条<alias name="stu" alias="s1"/>。可以通过stu拿对象,也可以通过s1 拿对象。

    4.当类中的一个成员变量为另一个类的对象时,在<property>子标签中可以通过ref引入,ref的值为一个<bean>标签的name或id值。

    5.同一个类可以配置多个对象,但是标识多个对象的id或name值要不同。

    注意:set方式底层会用到一个bean类的set方法,如果bean类的成员变量没有set方法却采用了set方式注入会报错。

    测试方法:

      /**
         * 基于set方法的注入
         */
        @Test
        public void set(){
            try{
                String[] path = {"com/cnblogs/ioc/set/set.xml"};
                ApplicationContext container = new ClassPathXmlApplicationContext(path);
                Student stu = (Student)container.getBean("stu");
                System.out.println(stu);
                
                Object a = container.getBean("A");
                System.out.println(a);
            } catch(Exception e) {
                e.printStackTrace();
            } 
        }

     

     结果:

     Student [sNo=1001, name=jack, age=12, sex=male, grade=三年级]
    A [desc=A组合了Student类对象, stu=Student [sNo=1001, name=jack, age=12, sex=male, grade=三年级]]

     

    2.set方式注入之集合的注入

    (1)准备一个B类,里面包括了各种集合:list,set,map,property

    B.java

    package com.cnblogs.bean;
    
    import java.util.List;
    import java.util.Map;
    import java.util.Properties;
    import java.util.Set;
    
    public class B {
        // list集合
        private List<String> list;
        // set集合
        private Set<String> set;
        // map
        private Map<String,String> map;
        // prop
        private Properties prop;
    
       // set和get方法
          
    }

    collection.xml

       <!-- 集合的注入 -->
        <bean name="coll" class="com.cnblogs.bean.B">
            <!-- list集合 -->
            <property name="list">
                <list>
                    <value>jack</value>
                    <value>tom</value>
                    <value>tina</value>
                </list>
            </property>
            <!-- set集合 -->
            <property name="set">
                <set>
                    <value>1001</value>
                    <value>1002</value>
                    <value>1003</value>
                </set>
            </property>
            <!-- map集合 -->
            <property name="map">
                <map>
                    <entry key="name" value="zhangsan"></entry>
                    <entry key="age" value="12"></entry>
                    <entry key="gender" value="male"></entry>
                </map>
            </property>
            <!-- properties集合注入 -->
            <property name="prop">
                <props>
                    <prop key="driver">com.mysql.jdbc.Driver</prop>
                    <prop key="username">study</prop>
                </props>
            </property>
        </bean>

     

    测试方法:和上面那个一样,就是xml的文件路径改一下。

     

    (2):如果一个list集合的泛型是一个类,也可以注入。

    HobbyGroup.java

    package com.cnblogs.bean;
    
    import java.util.List;
    
    // 兴趣小组
    public class HobbyGroup {
        private Long id;
        private String name;
        private List<Student> stu;
        
        public HobbyGroup() {
            super();
            // TODO Auto-generated constructor stub
        }
    
        public HobbyGroup(Long id, String name, List<Student> stu) {
            super();
            this.id = id;
            this.name = name;
            this.stu = stu;
        }
    // set和get方法
      
      // toString方法()
    }

    collection.xml

      <bean name="hg" class="com.cnblogs.bean.HobbyGroup">
            <property name="id" value="1"></property>
            <property name="name" value="羽毛球兴趣小组"></property>
            <property name="stu">
                <list>
                    <bean name="stu1" class="com.cnblogs.bean.Student" >
                        <property name="sNo" value="1001"></property>
                        <property name="name" value="jack"></property>
                        <property name="age" value="12"></property>
                        <property name="sex" value="male"></property>
                        <property name="grade" value="三年级"></property>
                    </bean>
                    <bean name="stu2" class="com.cnblogs.bean.Student">
                        <property name="sNo" value="1002"></property>
                        <property name="name" value="tom"></property>
                        <property name="age" value="13"></property>
                        <property name="sex" value="male"></property>
                        <property name="grade" value="三年级"></property>
                    </bean>
                    <bean name="stu3" class="com.cnblogs.bean.Student">
                        <property name="sNo" value="1003"></property>
                        <property name="name" value="tina"></property>
                        <property name="age" value="11"></property>
                        <property name="sex" value="female"></property>
                        <property name="grade" value="三年级"></property>
                    </bean>
                </list>
            </property>
        </bean>

     

    3.set注入之自动注入

    1.自动注入一般针对一个类中组合了另一类的对象。

    2.自动注入有byName注入和byType注入

    3.byName注入:spring容器会到当前的类中找property的名字,然后再根据这个名字去spring容器中找有没有和这个property名字相同的对象,有的话,

     就把这个对象当做参数放到setXxxx这个方法里面注入进来。(找到多个不会报错)

    4.byType注入:spring容器会根据set方法的参数类型去容器中找相匹配的对象,找到就注入,没找到就算了。如果找到多个会报错。

    5.可以在<beans>标签中加 default-autowire="byType",则下面的标签会根据byType方式自动注入。

    6.可以在<bean>标签中autowire=" "指定注入方式,该方式会屏蔽 default-autowire=" "。

    示例:

    同样用到com.cnblogs.bean.A类和com.cnblogs.bean.Student类。

    autowired.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-4.3.xsd"
        default-autowire="byName"
    >
    
        <bean name="stu" class="com.cnblogs.bean.Student">
            <property name="sNo" value="1001"></property>
            <property name="name" value="jack"></property>
            <property name="age" value="12"></property>
            <property name="sex" value="male"></property>
            <property name="grade" value="三年级"></property>
        </bean>
    <!-- byName --> <bean name="A1" class="com.cnblogs.bean.A"> <property name="desc" value="A组合了Student类对象,byName"></property> </bean> <!-- byType --> <bean name="A2" class="com.cnblogs.bean.A" autowire="byType"> <property name="desc" value="A组合了Student类对象,byType"></property> </bean> </beans>

    测试方法:

      @Test
        public void autowired(){
            try{
                String[] path = {"com/cnblogs/ioc/autowired/autowired.xml"};
                ApplicationContext container = new ClassPathXmlApplicationContext(path);
                // byName
                A a1 = (A) container.getBean("A1");
                System.out.println(a1);
                // byType
                A a2 = (A) container.getBean("A2");
                System.out.println(a2);
            } catch(Exception e) {
                e.printStackTrace();
            } 
        }

     结果:

    A [desc=A组合了Student类对象,byName, stu=Student [sNo=1001, name=jack, age=12, sex=male, grade=三年级]]
    A [desc=A组合了Student类对象,byType, stu=Student [sNo=1001, name=jack, age=12, sex=male, grade=三年级]]


    二:构造器注入

    构造器有分两种注入方式,一个根据参数类型注入,一个根据下标注入。

    1.根据参数类型注入

      同样用到com.cnblogs.bean.Student类。

      constructor.xml

       <!-- 根据参数类型 -->
        <bean name="stu1" class="com.cnblogs.bean.Student">
            <constructor-arg type="String" value="1001"></constructor-arg>
            <constructor-arg type="String" value="jack"></constructor-arg>
            <constructor-arg type="int" value="12"></constructor-arg>
            <constructor-arg type="String" value="male"></constructor-arg>
            <constructor-arg type="String" value="三年级"></constructor-arg>
        </bean>

    2.根据参数下标注入

      <!-- 根据下标 -->
        <bean name="stu2" class="com.cnblogs.bean.Student">
            <constructor-arg index="0" value="1002"></constructor-arg>
            <constructor-arg index="1" value="tina"></constructor-arg>
            <constructor-arg index="2" value="12"></constructor-arg>
            <constructor-arg index="3" value="female"></constructor-arg>
            <constructor-arg index="4" value="三年级"></constructor-arg>
        </bean>

     


    三、注解注入

    首先需要在xml文件中指定使用注解注入的包,springIoC容器读取这个文件的时候就会知道。

    anatation.xml:

    <context:component-scan base-package="com.cnblogs.ioc.anatation" />   

     

    com.cnblogs.ioc.annotation.Office.java

    package com.cnblogs.ioc.anatation;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class Office {
        private String num = "001";
        
        public Office(){
            
        }
        
        public Office(String num) {
            this.num = num;
        }
    
        public String getNum() {
            return num;
        }
    
        public void setNum(String num) {
            this.num = num;
        }
        
    }

     

    com.cnblogs.ioc.annotation.Car.java

    package com.cnblogs.ioc.anatation;
    import org.springframework.stereotype.Component;
    @Component
    public class Car { private double price; private String name; public Car(){ } public Car(double price, String name) { this.price = price; this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public String getName() { return name; } public void
    setName(String name) { this.name = name; } }

     

    com.cnblogs.ioc.annotation.Boss.java

    package com.cnblogs.ioc.anatation;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    import javax.annotation.Resource;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    
    @Component
    @Scope("prototype")
    public class Boss {
        private String name;
        
        @Autowired
        private Car car;
        
        @Resource
        private Office office;
        
        public Boss(){
            
        }
        
        public Boss(String name, Car car, Office office) {
            this.name = name;
            this.car = car;
            this.office = office;
        }
        
        public Boss( Car car, Office office) {
            this.car = car;
            this.office = office;
        }
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Car getCar() {
            return car;
        }
        
        
        public void setCar(Car car) {
            this.car = car;
        }
        public Office getOffice() {
            return office;
        }
        
        
        public void setOffice(Office office) {
            this.office = office;
        }
        
        @PostConstruct
        public void init(){
            System.out.println("初始化..");
        }
        
        @PreDestroy
        public void destory(){
            System.out.println("销毁...");
        }
        
    
    }

     测试方法:

      /**
         * 注解注入
         */
        @Test
        public void anatation(){
            try{
                String[] path = {"com/cnblogs/ioc/anatation/anatation.xml"};
                ApplicationContext container = new ClassPathXmlApplicationContext(path);
                
                Boss boss = (Boss) container.getBean("boss");
                System.out.println(boss.getName());
                System.out.println(boss.getCar());
                System.out.println(boss.getOffice());
                System.out.println(boss);
            } catch(Exception e) {
                e.printStackTrace();
            } 
        }

     

     结果

     初始化..
    null
    com.cnblogs.ioc.anatation.Car@50de0926
    com.cnblogs.ioc.anatation.Office@2473b9ce
    com.cnblogs.ioc.anatation.Boss@60438a68

     

     几个注解的作用:

    @Autowired
        1) @Autowired使用后需要在xml文件加入以下配置才能生效: <context:annotation-config/>
    
        2) @Autowired注解可以写在成员变量、setter方法、构造器函数上面
        
        3) @Autowired默认按照byType匹配的方式进行注入,如果没有一个bean的类型是匹配的则会抛异常,如果有多个bean的类型都匹配成功了,
        那么再按byName方式进行选择
        
        4) @Autowired如果最终匹配不成功(注意一定是一个都没有找到的情况)则会抛出异常,但是如果设置为 @Autowired(required=false),
        则最终匹配不成功没有不会抛出异常。
        
        5) @Autowired可以结合@Qualifier("beanName")来使用,则可以达到byName的效果
          
    
    
    @Resource
        1) @Resource使用后需要在xml文件加入以下配置才能生效:<context:annotation-config/>
    
        2) @Resource的作用和@Autowired差不多,只不过 @Resource是默认先用byName,如果找不到合适的就再用byType来注入
    
        3) @Resource有俩个属性,name和type,使用name属性则表示要byName匹配,使用type属性则表示要byType匹配
           
    
    @PostConstruct和@PreDestroy
        1) 标注了@PostConstruct注解的方法将在类实例化后调用
        2) 标注了@PreDestroy注解的方法将在类销毁之前调用
      
    
    @Component
        1) @Component注解可以直接定义bean,而无需在xml定义。但是若两种定义同时存在,xml中的定义会覆盖类中注解的Bean定义
    
        2) @Component注解直接写在类上面即可
    
        3) @Component有一个可选的参数,用于指定bean的名称
            @Component("boss")
            public class Boss{}
    
        4) @Component如果不指定参数,则bean的名称为当前类的类名小写
            //和上面例子的相关相同
            @Component
            public class Boss{}
    
        5) @Component使用之后需要在xml文件配置一个标签
            <context:component-scan/>
    
        6) <context:component-scan base-package="com.briup.ioc.annotation" /> 
            表示spring检查指定包下的java类,看它们是否使用了 @Component注解
    
        7) @Component定义的bean默认情况下都是单例模式的,如果要让这个bean变为非单例,可以再结合这个@Scope注解来达到目标@Scope("prototype")
    
    
        @Component是Spring中所有bean组件的通用形式, @Repository @Service @Controller 则是 @Component的细化,用来表示更具体的用例,
        分别对应了持久化层、服务层和表现层。但是至少到现在为止这个四种注解的实质区别很小(甚至几乎没有),都是把当前类注册为spring容器中
        的一个bean
    
    
    注意:
        1.component-scan标签默认情况下自动扫描指定路径下的包(含所有子包)
    
        2.component-scan标签将带有@Component @Repository @Service @Controller注解的类自动注册到spring容器中
    
        3.component-scan标签对标记了@Required @Autowired @PostConstruct @PreDestroy @Resource @WebServiceRef @EJB  
        @PersistenceContext @PersistenceUnit等注解的类进行对应的操作,使注解生效
        
        4.component-scan标签包含了annotation-config标签的作用

     

     

     

     

  • 相关阅读:
    SSDB安装配置记录
    Ubuntu上通过nginx部署Django笔记
    PyCharm创建virtualenv方法
    Python3--列表生成式
    K最近邻算法项目实战
    K最近邻算法
    人工智能之机器学习
    C#把汉字转换成16进制(HEX)并向串口发送数据
    Ubuntu-18.04.2系统 Nginx+uWSGI+Django 部署生产环境
    HTTP响应状态码说明
  • 原文地址:https://www.cnblogs.com/yangji0202/p/10863883.html
Copyright © 2020-2023  润新知