一、Spring IOC 容器概述

1. 概述
  spring-aop 模块提供了面向切面编程(AOP)的实现,可以定义诸如方法拦截器和切入点等,从而使实现功能的代码彻底的解耦出来。使用源码级的元数据,可以用类似于.Net属性的方式合并行为信息到代码中。

2. 作用

  • IOC(Inversion of Control):控制反转,不是什么技术,而是一种设计思想,旨在解决各层耦合。在Java开发中,IOC意味着将你设计好的对象交给容器控制,而不是传统的在对象内部直接控制;
  • DI(Dependency Injection):依赖注入,IOC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象,这一点是通过依赖注入来实现的。

IOC:IOC容器自动创建对象,ID:从容器中自动寻找对象给对象属性赋值。

二、创建IOC容器

1. 容器的类的继承关系
容器的类关系图

2. 创建容器的几种方式

常用:

//方式1:加载类路径下的配置文件
@Test
public void createObj(){
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
}
//方式2:加载注解类
@Test
public void createObj2(){
    // 加载指定的注解类的方式创建容器
    ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
}

三、IOC容器 -- 控制反转(创建对象)

常用两种方式:

1. 调用无参构造器

<bean id="user" class="com.zz.entity.User"></bean>

2. 调用带参构造器


四、IOC容器 -- 依赖注入(给对象属性赋值)

1. 调用带参构造器

applicationContext.xml

<!-- 通过构造器给对象属性赋值 -->
<!--  constructor-arg 通过构造函数给对象属性赋值
    index 表示第几个参数,从0开始
    value 表示参数值(直接给)
    ref   也是给参数赋值,值是引用容器中的另外的对象。
    name  对应构造函数的形参名称
    type  参数类型
-->

<!-- 调用Product有参构造函数 -->
<bean id="product" class="com.zz.entity.Product">
    <constructor-arg name="id" type="int" value="123"/>
    <constructor-arg name="name" type="String" ref="str"/>
</bean>

2. 调用set方法(property)

Product.class

// 提供set方法给对象属性赋值
public void setId(int id) {// id 表示属性
    this.id1=id;
}

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

applicationContext.xml

<!--2. 调用set方法给对象属性赋值-->
<!--
    property 给对象属性赋值
        name 相当于调用public void setName(String name)方法
        name是一个属性,即使setName 的 Name第一个字母小写
        value 传入set方法的值
        ref   值引用的是ioc容器中的其他的对象。
-->

<!-- 调用默认的无参构造函数 -->
<bean id="product" class="com.itheima.entity.Product">
    <property name="id" value="888"></property>
    <property name="name" ref="str"></property>
</bean>

<!--需求:创建一个字符串值是Jack  String str = new String(Jack);-->
<bean id="str" class="java.lang.String">
    <constructor-arg value="mike"></constructor-arg>
</bean>

补充:调用Set方法(P命名空间)
<bean id="product" class="com.zz.entity.Product" p:id="123" p:name-ref="str"/>

五、Dao层、Service层 解耦

  • 创建dao层对象,创建service层对象
  • dao层对象注入service层中dao层对象
  • 创建容器,getBean获取service对象,调用重写方法

六、使用注解配置IOC

概念:注解配置和XML配置要实现的功能都是一样的,都是要降低程序间的耦合,只是配置的形式不一样。在实际开发中通常是XML和注解两者混合使用,举例:dao层用注解创建的对象,在service层用xml创建的对象一样可以注入dao。

七、IOC常用注解

1. @Component --创建对象

  • 作用:把对象交给 springIOC 容器来管理,相当于在 xml 中配置一个 bean,<bean id="..." class="..."/>

  • 属性:value,指定 bean 的 id,如果不指定 value 属性,默认 bean 的 id 是当前类的类名,首字母小写

Other创建对象注解
  提供更加明确的语义化,作用和属性与@Component 一样

  • @Controller:一般用于表现层的注解
  • @Service:一般用于业务层的注解(service)
  • @Repository:一般用于持久层的注解(dao)
  • @Component:一般用于工具类的注解
@Component
public class User{

    public User(){
        system.out.println("创建对象!");
    }
}

2. @Autowired --注入数据
  自动按照类型注入,当使用注解注入属性时,set 方法可以省略。它只能注入其他 bean 类型,当有多个类型匹配时,使用要注入的对象变量名称作为 bean 的ID在 spring 容器查找,找到了就可以注入成功,找不到就报错。

a)定义到字段上

/**
 * @Autowired注入数据的注解
 * 1. 默认根据字段类型注入
 *    自动去IOC容器中找该字段类型的对象,注入进来
 * 2. 如果该字段类型再容器中有多个对象
 *    2.1 按照字段名称去容器中找该名称对应的对象注入进来
 *    2.2 如果按照字段名称去容器中没有找到对象,就报错 --NoUniqueBeanDefinitionException
 * 3. 注解属性
 *    required 默认为true,如果去容器中没有找到对象注入,就报错
 *             false,如果去容器中没有找到对象注入,不会报错
 */
 @Autowired
 private String name;

 //下面代码相当于 AccountDao accountdao = new AccountDaoImpl();  
 @Autowired
 private AccountDao accountdao;

b)定义到方法上

/**
 * @Autowired注入数据的注解,定义到方法上
 * 1. 默认根据参数类型,去容器找该类型对应的对象注入
 * 2. 如果类型有多个,会根据参数名称去容器中找对象注入
 *    如果根据名称没有找到就报错
 *
 */
 @Autowired
 public void setName(String name){     //根据参数名称
     System.out.println(name);
 }

3. @Qualifier

  • 作用:在自动按照类型注入的基础之上,再按照 Bean 的id注入。它在给字段注入时不能独立使用,必须和@Autowire 一起使用,但是给方法参数注入时,可以独立使用。

  • 属性:value,指定 bean 的 id

4. @Resource

  • 作用:直接按照 Bean 的id注入或者类型注入,它也只能注入其他 bean 类型,与@Autowired注解功能类似;
  • 属性:name指定bean的id;
  • 补充:1.8版本可以使用,后面的JDK版本中取消了该注解支持。
    s
/**
 * 用于DI依赖注入的注解
 */
@Component("user")
public class User {

    // 一旦指定了@Qualifier,这里只会按照名称注入
    // 会去IOC容器中找 name名称对应的对象注入
    @Qualifier("name1")
    private String name;
}

5. @Value

  • 作用:注入基本数据类型和 String 类型数据的
  • 属性:value用于指定值
//1.@Value 给简单类型的字段直接赋值
//2.也可以获取配置文件值:@Value("${key}")
@Value("zz")
private String name;

6. 其他注解

      XML配置       VS       注解
<bean id="" class="" 
     scope=""          使用@Scope注解取代
     lazy-init=""      使用@Lazy注解取代
     init-method=""    使用@PostConstruct注解取代
     destroy-method="" 使用@PreDestroy注解取代
/>

八、XML OR 注解 选择

1. 优势

  • XML的优势:修改时不用改源码,不涉及重新编译和部署问题

  • 注解的优势:开发简单,维护方便(找到类就相当于找到了对应的配置)

2. 对比
XML配置和注解配置对比

3. 小结
  基于注解的 SpringIOC 配置中,bean对象的特点和基于XML配置是一模一样的,XML配置可以与注解配置一起使用,目前开发比较常用的是:XML + 注解 混合使用。
  
- XML:配置一些全局的对象(如:DataSource/JdbcTemplate..)
- 注解:每一个模块的 dao/service 等对象的创建可以用注解,简化配置

九、总结

1. 常用的注解
- @Component:创建对象加入容器,例如:工具类、其他组件
- @Repository:创建对象加入容器,例如:标识数据库访问层的组件
- @Service:创建对象加入容器,例如:标识乐屋逻辑层的组件
- @Controller:创建对象加入容器,例如:标识控制层的组件

  • @Autowired:从容器中找对象,给属性赋值,根据类型、名称去容器中找
  • @Qualifier:结合Autowired使用,可以指定按照名称去容器找对象注入
  • @Value:给简单类型属性直接赋值/获取配置文件值 @Value(“${key}”)
  • @Resource:从容器中找对象,给属性赋值。 根据名称、类型去容器中查找

  • @Scope:单例/多例

  • @PostConstruct:初始化方法,创建对象后执行
  • @PreDestroy:销毁先执行
  • @Lazy:延迟初始化

2. 使用注解零配置
- @Configuration:取代bean.xml
- @ComponentScan:注解扫描
- @Import:导入其他配置类
- @Bean:修饰方法,自动把方法返回值放入容器
- @PropertySource:加载外部配置文件
- @Value:获取@ PropertySource加载的配置文件的值


星河滚烫,你是人间理想