Spring框架-IOC/DI详细学习

一.IOC/DI概念html

  参考博客:http://www.javashuo.com/article/p-nnnjsjvx-gk.htmljava

   IOC(inversion of control, 控制反转)是一种设计思想,而不是一种技术. IOC意味着将咱们设计好的对象交给容器控制,而不是交给对象内部控制.它指导咱们设计出松耦合,更优良的程序. 传统程序都是由在类内部主动建立依赖对象来使用, 从而致使类与类之间高耦合, 难于测试; 有了IOC容器,把建立和查找依赖对象的控制权交给了容器, 由容器进行注入组合对象,因此对象和对象之间是松耦合, 这样使得程序的整个体系结构很是灵活.web

   实际上,IOC能够看作是一个大型中介, 将对象的信息登记其中,这个对象是什么, 这个对象又须要什么 ,由中介公司给对象分配它须要的资源, 以及将对象分配给须要它的对象.Spring在这个过程当中控制着对象的生命周期和对象间的关系, 全部类的建立和销毁都由Spring控制, 而不是须要它们的类控制, 这就是控制反转.spring

   DI(Dependency Injection, 依赖注入)是IOC的一个重点,它实现IOC的一种方法,或者说DI是IOC的另外一种说法 , 它负责实现IOC动态地向某个对象提供它所须要的其余对象. 好比一我的须要一根扫把, 不是由这我的本身去作扫把, 而是由Spring将作好的扫把给他,  而这我的全程须要作的,就是喊我要一根扫把. 什么叫作依赖, 人须要扫把, 人就对扫把有了依赖. 而DI就是根据这个依赖,将扫把分配给这我的的.session

 

二.IOC的使用app

  参考博客:http://www.javashuo.com/article/p-hksdeorr-by.html函数

    IOC实现的两种方式: XML配置  ,  Spring注解测试

    依赖注入的两种形式: Setter依赖注入, 构造方法依赖注入 ui

 

1.XML配置的两种依赖注入形式:this

  (1)Setter依赖注入: 首先建立一个Book类,将其属性设置好setter,getter方法

public class Book {
    private int id;
    private String name;
    private User user;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

而后在applicationContext.xml中添加bean, 告诉Spring二者的依赖关系,实现注入

    <bean name="book" class="pojo.Book">
        <property name="name" value="book1"></property>
        <property name="user" ref="user"></property>   <!--这里将book依赖了user,所以在咱们获取book时,会获取指定的user对象 -->
    </bean>

    <bean name="user" class="pojo.User">
        <property name="name" value="user1"></property>
        <property name="age" value="12"></property>
    </bean>

 

(2)构造方法依赖注入:

咱们将BOOK类中添加了一个两个参数的构造方法,而后在xml文件中肯定两个参数的值,从而让spring容器可以创造对象

public class Book {
    private int id;
    private String name;
    private User user;

    //Constructor
    public Book(String name,User user){
        this.name = name;
        this.user = user;
    }
}

xml文件中的配置为: 指定了构造器有两个参数, 第一个参数是String , 第二个参数指向了另外一个bean

    <bean name="book" class="pojo.Book">
        <constructor-arg type="java.lang.String">   <!-- 指定参数的类型,能够在有多个构造器时不产生歧义 -->
            <value>Adel</value>
        </constructor-arg>
        <constructor-arg>
            <ref bean="user"></ref>
        </constructor-arg>
    </bean>

    <bean name="user" class="pojo.User">
        <property name="name" value="user1"></property>
        <property name="age" value="12"></property>
    </bean>

或者能够这样写构造参数:

    <bean name="book" class="pojo.Book">
        <constructor-arg name="name" value="lala"></constructor-arg>
        <constructor-arg name="user" ref="user"></constructor-arg>
    </bean>

又或者这样写:

    <bean name="book" class="pojo.Book">
        <constructor-arg index="0" value="lala"></constructor-arg>
        <constructor-arg index="1" ref="user"></constructor-arg>
    </bean>

 

 (3) Scope对象做用域:  从Spring容器中获取的对象的做用域能够修改,默认的做用域为单例, 具体以下

  • Singleton :  每一个Spring容器做用域中,一个bean定义 只对应一个对象实例 
  • Prototype:  一个bean定义对应多个对象实例
  • Request:    一个bean定义做用于HTTP request 生命周期, 指每一个HTTP request 从Spring获取的对象实例不同. 仅在基于web的Spring ApplicationContext中有效.
  • Session:    一个bean定义做用域HTTP session 生命周期,
  • Global Session:      一个bean定义做用域全局的HTTP session 生命周期.
  • Application:       一个bean定义做用于整个ServletContext生命周期

其在配置中写在bean的属性Scope中:

    <bean name="book" class="pojo.Book" scope="singleton">
        <constructor-arg index="0" value="lala"></constructor-arg>
        <constructor-arg index="1" ref="user"></constructor-arg>
    </bean>

 

   (4)延迟初始化bean:    一般ApplicationContext默认在启动时将全部singleton bean提早实例化. 一般提早实例化是好事,避免某些错误由于延迟实例化而不被提早发现. 可是若是想防止提早实例化, 好比你只须要用到book对象, 而不须要它初始化它的user对象, 就能够用lazy-init属性来控制

    <bean name="book" class="pojo.Book" >
        <constructor-arg index="0" value="lala"></constructor-arg>
        <constructor-arg index="1" ref="user"></constructor-arg>
    </bean>

    <bean name="user" class="pojo.User" lazy-init="true">
        <property name="name" value="user1"></property>
        <property name="age" value="12"></property>
    </bean>

 

(5)回调方法:  初始化回调函数init 

public class Book {
    private int id;
    private String name;
    private User user;

//    Constructor
    public Book(String name,User user){
        this.name = name;
        this.user = user;
    }

    public void init(){
        System.out.println("建立了一本书");
    }

    public void destroy(){
        System.out.println("销毁了一本书");
    }
}

在xml文件中设置初始化回调函数,就会在建立时调用

    <bean name="book" class="pojo.Book" init-method="init" destroy-method="destroy" >
        <constructor-arg index="0" value="lala"></constructor-arg>
        <constructor-arg index="1" ref="user"></constructor-arg>
    </bean>

 

 

2.Spring注解:

    注解会削减一些配置的工做量, 可是代码的耦合度会增长,  应当根据须要使用注解

(1)@Component注解:  这个注解和<bean>做用相似, 经过增长@Component()注解中的参数,指定其在Spring容器中的名称. 若是不写,则是默认其在Spring容器中的名称为类名的小写 如User类 在Spring容器中默认名称为 user

@Component("user")
public class User {
    private int id;
    private int age;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

在配置文件中,即便没有user这个bean , 其它bean也能够用到

    <bean name="book" class="pojo.Book" init-method="init" destroy-method="destroy" >
        <constructor-arg index="0" value="lala"></constructor-arg>
        <constructor-arg index="1" ref="user"></constructor-arg>
    </bean>

    <!--<bean name="user" class="pojo.User" lazy-init="true">-->
        <!--<property name="name" value="user1"></property>-->
        <!--<property name="age" value="12"></property>-->
    <!--</bean>-->

 

(2)@Auotowired 注解:   在Spring中,可使用 @Autowired 注解经过setter方法构造函数字段自动装配Bean。

 
 
经过setter方法
public class Book {
    private int id;
    private String name;
    private User user;

    public User getUser() {
        return user;
    }

    @Autowired
    public void setUser(User user) {
        this.user = user;
    }
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

这样,即便在applicationContext.xml文件中没有设置要在book中user依赖哪一个对象, Spring容器也会自动装配

    <bean name="book" class="pojo.Book"  >
        <property name="name" value="lala"></property>
        <property name="id" value="12"></property>
    </bean>

    <bean name="user" class="pojo.User" lazy-init="true">
        <property name="name" value="user1"></property>
        <property name="age" value="12"></property>
    </bean>

 

经过构造函数:

public class Book {
    private int id;
    private String name;
    private User user;

//    Constructor
    @Autowired
    public Book(User user){
        this.user = user;
    }
}

 

经过字段:

public class Book {
    private int id;
    private String name;
    @Autowired
    private User user;
}

 

(3)@Resource注解  : 这个注解与@Autowired不一样是, 它能够指定装配对象的名称,或者类型,或者二者都指定

如book和user

@Component("u")
public class User {
    private int id;
    private int age;
    private String name;
//setter 和 getter
}
@Component("b")
public class Book {
    private int id;
    private String name;
    @Resource(name = "u")
    private User user;
//setter和getter
}
@Component("b")
public class Book {
    private int id;
    private String name;
    @Resource(name = "u",type = User.class)
    private User user;
}

或者这样

@Component("b")
public class Book {
    private int id;
    private String name;
    @Resource(name = "u",type = User.class)
    private User user;
 
 
各类注解的解释, 如下转自  http://www.javashuo.com/article/p-hksdeorr-by.html

@Service用于注解业务层组件(咱们一般定义的service层就用这个)

@Controller用于注解控制层组件(如struts中的action)

@Repository用于注解数据访问组件,即DAO组件

@Component泛指组件,当组件很差归类的时候,咱们可使用这个注解进行注解。

装配注解主要有:@Autowired、@Qualifier、@Resource,它们的特色是:

一、@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;

二、@Autowired默认是按照类型装配注入的,若是想按照名称来转配注入,则须要结合@Qualifier一块儿使用;

三、@Resource注解是由J2EE提供,而@Autowired是由spring提供,故减小系统对spring的依赖建议使用@Resource的方式;若是Maven项目是1.5的JRE则需换成更高版本的。

四、@Resource和@Autowired均可以书写注解在字段或者该字段的setter方法之上

五、@Autowired 能够对成员变量、方法以及构造函数进行注释,而 @Qualifier 的注解对象是成员变量、方法入参、构造函数入参。

六、@Qualifier("XXX") 中的 XX是 Bean 的名称,因此 @Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了。

七、@Autowired 注释进行自动注入时,Spring 容器中匹配的候选 Bean 数目必须有且仅有一个,经过属性required能够设置非必要。

八、@Resource装配顺序
  8.1. 若是同时指定了name和type,则从Spring上下文中找到惟一匹配的bean进行装配,找不到则抛出异常
  8.2. 若是指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  8.3. 若是指定了type,则从上下文中找到类型匹配的惟一bean进行装配,找不到或者找到多个,都会抛出异常
  8.4. 若是既没有指定name,又没有指定type,则自动按照byName方式进行装配;若是没有匹配,则回退为一个原始类型进行匹配,若是匹配则自动装配;

 

如下转自博客:https://blog.csdn.net/qq_22583741/article/details/79589910 

1.@Component取代<bean class="">
@Component("id") 取代 <bean id="" class="">
2.web开发,提供3个@Component注解衍生注解(功能同样)取代
@Repository :dao层
@Service:service层
@Controller:web层
3.依赖注入,给私有字段设值,也能够给setter方法设值

普通值:@Value(" ")引用值: 方式1:按照【类型】注入 @Autowired 方式2:按照【名称】注入1 @Autowired @Qualifier("名称") 方式3:按照【名称】注入2 @Resource("名称") 4.生命周期 初始化:@PostConstruct 销毁:@PreDestroy 5.做用域 @Scope("prototype") 多例 注解使用前提,添加命名空间,让spring扫描含有注解类

相关文章
相关标签/搜索