dubboreference怎么注入spring管理_Spring入门之IOC

Spring是一个框架,也是一个容器,其核心技术是IOC、AOP,实现程序的解耦合或者是尽可能减少耦合。在Spring容器中存放的是各种Java对象,容器可以完成对象的创建、对象之间关系的管理。开发中使用的Dao类、Service类、Controller类、工具类等可以放入容器中,而实体类或者需要由其他容器管理的对象如由tomcat管理的Servlet、Filter、Listener等不需要放在Spring容器中。 IOC(Inversion of Control)是一个概念,是一种思想,将传统上由程序代码直接操控的对象调用权交给容器,通过容器来实现对象的装配和管理。控制反转就是对对象控制权的转移,从程序代码本身反转到了外部容器,通过容器实现对象的创建,属性赋值, 依赖的管理。 IOC技术的具体实现使用的的是依赖注入。DI(Dependency Injection),程序代码不做定位查询,这些工作由容器自行完成。Spring使用DI的技术,底层靠的是反射机制。 DI给属性赋值的方式有构造函数注入和set注入。构造函数注入是Spring调用有参构造方法,set注入是Spring调用类 的set方法实现属性赋值。 前面介绍的都是文字概念,下面具体介绍一下相关的知识。 首先,前面说到在Spring容器中存放的是各种Java对象,容器可以完成对象的创建,那么Spring是怎么完成对象的创建的呢?在Spring中,Java对象称之为bean。 是配置文件的根标签,在这个标签下进行Java对象的创建。 创建对象即实例化Bean,在Spring中有三种方式:使用默认无参构造方法创建对象、使用实例工厂的方法创建对象、使用静态工厂的方法创建对象。最常用的是使用默认无参构造方法创建对象。如下代码所示:
一个bean标签声明一个对象,上面的代码等价于:
Someservice someservice=new SomeserviceImpl();

Spring把创建好的对象放进Map集合中:

(“someservice”:对象)(“someservice1”:对象)

使用的时候根据id这个唯一的key就可以获取对象。

getBean("someservice");

bean标签中有以下细节:

id:自定义的对象名称,要求是唯一值, 表示在Spring中的对象名称,通过这个名称可以从Spring中找到对象,获取对象。 class:类的全限定名称,不能是接口(Spring使用反射创建对象);class可以是非自定义的对象,如java.util.Date也可以用Spring创建对象。 scope:指定bean对象的作用域(对象的存在范围和可见性)。2eac0ebedf1aedd808c3b1521900c4d9.png可以通过bean标签下的scope改变bean对象的作用域:
 
DI给属性赋值的方式有构造函数注入和set注入。注入的意思就是给属性赋值。首先看构造函数注入:
package org.zhu.service.impl;import java.util.Date;public class Student {    private String name;    private int age;    private Date birthday;    public Student(String name, int age, Date birthday) {        this.name = name;        this.age = age;        this.birthday = birthday;    }    public void setName(String name) {        this.name = name;    }    public void setAge(int age) {        this.age = age;    }    public void setBirthday(Date birthday) {        this.birthday = birthday;    }    @Override    public String toString() {        return "Student{" +                "name='" + name + '\'' +                ", age=" + age +                ", birthday=" + birthday +                '}';    }}
<?xml version="1.0" encoding="UTF-8"?>       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">                
@Test    public void test3(){        String config="applicationContext.xml";        ApplicationContext ac=new ClassPathXmlApplicationContext(config);        Student mystudent = (Student) ac.getBean("mystudent");        System.out.println(mystudent);    }

493ae45ec19b352a753638b6e75b49f7.png

找给谁赋值:

index:参数在构造函数中的索引位置,从0开始。

type:参数在构造函数中的数据类型。

name:参数在构造函数中的名字。
赋的什么值:
value:基本数据类型+String
ref:引用其他的bean
       构造函数注入必须有有参构造函数,必须注入数据,不管用不用得到,改变了Bean实例化对象的方式,不能使用默认的无参构造了。在类中要写有参构造方法。实际开发中一般不用这种方法。 接着介绍set注入方法。
public class Student {    private String name;    private Address address;    private String[] books;    private List hobbies;    private Map card;    private Set games;    private String wife;    private Properties info;    public Address getAddress() {        return address;    }    public void setAddress(Address address) {        this.address = address;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String[] getBooks() {        return books;    }    public void setBooks(String[] books) {        this.books = books;    }    public List getHobbies() {        return hobbies;    }    public void setHobbies(List hobbies) {        this.hobbies = hobbies;    }    public Map getCard() {        return card;    }    public void setCard(Map card) {        this.card = card;    }    public Set getGames() {        return games;    }    public void setGames(Set games) {        this.games = games;    }    public String getWife() {        return wife;    }    public void setWife(String wife) {        this.wife = wife;    }    public Properties getInfo() {        return info;    }    public void setInfo(Properties info) {        this.info = info;    }    @Override    public String toString() {        return "Student{" +                "name='" + name + '\'' +                ", address=" + address.getAddress() +                ", books=" + Arrays.toString(books) +                ", hobbies=" + hobbies +                ", card=" + card +                ", games=" + games +                ", wife='" + wife + '\'' +                ", info=" + info +                '}';    }}
public class Address {    private String address;    public String getAddress() {        return address;    }    public void setAddress(String address) {        this.address = address;    }}
<?xml version="1.0" encoding="UTF-8"?>       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd">                                                                                                西游记                红楼梦                三国演义                水浒传                                                                唱                跳                Rap                篮球                                                                                                                                                LOL                王者农药                和平精英                                                                                119110022293                621456879                        
public class testtt {    public static void main(String[] args) {        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");        Student stu = (Student) context.getBean("stu");        System.out.println(stu.toString());    }}
Student{name='zhulin', address=清水, books=[西游记, 红楼梦, 三国演义, 水浒传], hobbies=[唱, 跳, Rap, 篮球], card={姓名=朱琳, 学号=119110022293}, games=[LOL, 王者农药, 和平精英], wife='null', info={学号=119110022293, 银行卡号=621456879}}
此外还有p命名空间注入、p命名空间注入,本质都是set注入方式。 P命名空间注入 : 需要在头文件中加入约束文件:
导入约束 : xmlns:p="http://www.springframework.org/schema/p"  
c 命名空间注入 : 需要在头文件中加入约束文件:
导入约束 : xmlns:c="http://www.springframework.org/schema/c"  
在上面的代码中,ApplicationContext即表示Spring容器,通过容器获取对象,它是BeanFactory的子接口,BeanFactory是Spring容器的顶层接口。ApplicationContext 用来获取加载配置文件,使用ApplicationContext接口,只要一读取配置文件,默认情况下就会创建对象,而BeanFactory是什么时候使用对象什么时候创建。ClassPathXmlApplicationContext是ApplicationContext接口的实现类,它从类的根路径下加载配置文件。此外,还有: FileSystemXmlApplicationContext:从磁盘路径加载配置文件 AnnotationConfigApplicationContext:使用注解配置容器对象 这两个实现类。 对于引用类型,Spring框架可以根据某些规则给其赋值,常见的规则是: byName:根据名称自动注入

byType:根据类型自动注入

当配置文件中被调用者 bean 的 id 值与代码中调用者 bean 类的属性名相同时,可使用 byName 方式,让容器自动将被调用者 bean 注入给调用者 bean。容器是通过调用者的bean类的属性名与配置文件的被调用者 bean的id进行比较而实现自动注入的。例如,在Student类中,School类型的属性名是”school“,那么在xml配置文件中:
<?xml version="1.0" encoding="UTF-8"?>       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd">                                                                    
使用 byType 方式自动注入,要求配置文件中被调用者 bean 的 class 属性指定的类, 要与代码中调用者 bean 类的某引用类型属性类型同源。即要么相同,要么有 is-a 关系(子 类,或是实现类)。但这样的同源的被调用 bean 只能有一个。多于一个,容器就不知该匹配 哪一个了,会报异常:
NoUniqueBeanDefinitionException
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd">            <bean id="myStudent" class="com.zhu.Student" autowire="byType">        <property name="name" value="周武" />        <property name="age" value="22"/>                    bean>        <bean id="mySchool" class="com.bjpowernode.School">      <property name="name" value="清华大学" />      <property name="address" value="北京的海淀区" />    bean>        beans>
此外,还可以使用注解实现自动装配: @Autowires:默认ByType,实体类可以去掉set方法,xml可以省略id。 @Qualifier(value=“cat”)     

根据类型自动装配,加上@Qualifier则可以根据byName的方式自动装配。

    @Autowired    @Qualifier(value="cat11")    private Cat cat;    @Autowired    @Qualifier(value="dog22")    private Dog dog;    private String str;
@Resource :先ByName再ByType

它们的作用相同都是用注解方式注入对象,但执行顺序不同。@Autowired先byType,@Resource先byName。在下面的注解知识部分还会介绍这几个注解的用法。

最后,介绍关于使用注解开发的知识。想要使用注解形式,必须得要引入aop的包,在配置文件当中,还得要引入一个context约束。
<?xml version="1.0" encoding="UTF-8"?>      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.xsd       http://www.springframework.org/schema/context       http://www.springframework.org/schema/context/spring-context.xsd">                     

context:component是声明组件扫描器,指定注解所在的包名,让框架找到注解,base-package指定注解在项目中的包名,框架会扫描这个包和子包中所有类的注解,按照注解的功能,创建对象,赋值属性。

                                
首先看第一个注解@Component,用来创建对象,通过类的无参构造方法,同一样。
@Component(value="mystudent1")public class Student {    @Value("张三")    private String name;    private int age;    private Date birthday;    public Student() {    }    public Student(String name, int age, Date birthday) {        this.name = name;        this.age = age;        this.birthday = birthday;    }    public void setName(String name) {        this.name = name;    }    @Value("18")    public void setAge(int age) {        this.age = age;    }    public void setBirthday(Date birthday) {        this.birthday = birthday;    }    @Override    public String toString() {        return "Student{" +                "name='" + name + '\'' +                ", age=" + age +                ", birthday=" + birthday +                '}';    }}
value可以省略,也可以在@Component后什么都不写,默认的对象名是类名首字母变成小写,此外,@Component还有三个衍生注解:@Repository :用于对 DAO 实现类进行注解 @Service :用于对 Service 实现类进行注解 @Controller: 用于对Controller实现类进行注解

这三个注解与@Component 都可以创建对象,但这三个注解还有其他的含义,@Service 创建业务层对象,业务层对象可以加入事务功能,@Controller 注解创建的对象可以作为处理器接收用户的请求。它们可以给项目分层。

接着看第五个注解@Value。@Value给简单类型的属性赋值。value 是String类型的,表示简单类型的属性值,它的位置可以在属性定义的上面, 无需set方法,是常用的方式 ,也可以在set方法上面。 第六个注解@Autowired,@Autowired给引用类型赋值,默认按byType注入,在@Autowired的基础上,再加入@Qualifier可以按照byName注入。@Qualifier在给引用属性注入时不能单独使用,但在给方法参数注入时可以单独使用。 这里有个注意点,@Autowired默认情况下要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) 。

第八个注解@Resource ,@Resource默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

前面已经说过,@Autowired和@Resource作用相同,都是用注解方式注入对象,但执行顺序不同。@Autowired先byType,@Resource先byName。

最后,总结一下XML和注解。XML可以适用任何场景 ,结构清晰,配置和代码是分离的,在 xml 中做修改,无需编译代码,只需重启服务器即可将新的配置加载。但是其编写麻烦,效率低,大型项目过于复杂。注解不是自己提供的类使用不了,开发简单、方便、直观、高效,代码少,没有配置文件的书写那么复杂,但是它以硬编码的方式写入到 Java 代码中,修改是需要重新编译代码的。在实际开发中将两种方式结合起来,能用注解的用注解,不能用注解的用XML。

版权声明:本文为weixin_32059007原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。