Spring-01--IOC

Spring是什么:

Spring是分层的javaEE轻量级开源框架,以IOC(控制反转)和AOP(面向切面编程)为内核的框架。

Spring的优势:

方便解耦,简化开发。
AOP编程的支持。
声明事务的支持。
方便程序测试。
方便集成各种优秀框架,
降低javaEEAPI的使用难度。

IOC的概念和作用:

IOC:控制反转,降低程序之间的耦合,解除代码中的依赖关系。是一个map结构。
之前我们获取对象采用的是new,是主动的。用配置文件以后获取对象是从工厂要,由工厂查找或者创建对象,是被动的,这种被动接收方式获取对象的思想就是控制反转,是spring框架核心之一。

程序的耦合
耦合:程序之间的依赖关系,包括类之间的依赖,方法间的依赖。
解耦:降低程序之间的依赖关系。
在实际开发中要做到:编译期不依赖,运行时才依赖。
解耦的思路
1 使用反射来创建对象,而避免使用new关键字。
2 通过读取配置文件来获取要创建的对象权限权限定类名。

Bean:在计算机英语中是有可反复使用组件的含义。
JavaBean:用java语言编写的可反复使用的组件。它就是创建我们service和Dao对象的。
方式:
1 需要一个配置文件 来配置我们的service和Dao。
配置内容:唯一标识=权限定类名(key=value)
2 通过配置文件中的配置内容来反射创建对象。
配置文件可以是xml格式也可以是properties,(在main---resources目录下创建XXX.properties或者XXX.xml ,XXX可以是叫任意,此处我叫它bean)


spring的搭建

1 建立maven项目,在pom.xml中写导入坐标下如下代码

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
</dependencies>

2 在src----main----resources下创建bean.xml(不一定叫bean 只要不是中文叫什么都行)在里面添加约束。

<?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">


 </beans> 

3 把对象的创建交给Spring来管理

<?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">
 <!--把对象的创建交给spring来管理-->
 <!--id="获取时的ID"      class ="反射时要创建的权限另类名"-->
 <!--创建一个AccountServiceImpl类的对象 为其指定一个ID="accountService"-->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>
    <!--创建一个AccountDaoImpl 类的对象 为其指定一个ID="AccountDao"-->
    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>
 </beans> 

4 在表现层获取spring的核心容器,并根据id获取对象。

public static void main(String[] args){
    //1 获取核心容器
    ApplicationContext ac = new ClassPathXmlApplicationContext("beann.xml");
   
   //2根据id获取bean对象
        IAccountService as =(IAccountService)ac.getBean("accountService");
        IAccountDao adao =ac.getBean("accountDao",IAccountDao.class);
  
    System.out.println(as);
    System.out.println(adao);
}
//打印消息为:com.itheima.serivce.impl.AccoutnServiceImpl@5e5792a0
//                     com.itheima.dao.impl.AccountDaoImpl@26653222

ApplicationContext的三个常用实现类
ClassPathXMLApplicationContext(常用):它可以加载类路径下的配置文件 要求配置文件必须在类路径下。不在的话加载不了,也就是说加载不了就创建不了容器。

FileSystemXmlApplicationContext:它可以加载磁盘任意路径下的配置文件(必须有访问权限)
AnnotationConfigApplicationContext:读取注解创建容器。

核心容器的两个接口引发的问题
ApplicationContext:(用的比较多)(单例模式适用)它在构建核心容器时,创建对象采取的策略是采用立即加载方式 也就是说只要读取完配置文件马上创建配置文件中的配置对象。
BeanFactory:(多列模式适用)它在构建核心容器的时候 创建对象采取的策略是延迟加载方式,也就是说id什么时候获取对象了 才什么时候真正的创建对象。

spring对bean的管理细节

1 创建bean的三种方式
2 bean对象的作用范围
3 bean对象的声明周期

1 创建bean的三种方式
第一种:使用默认构造函数创建。在spring的配置文件中使用bean标签,配合id和class属性之后,没有其他标签时,采取的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。

  <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>

第二种:使用普通工厂中的方法创建对象(使用某个类中的方法创建对象并存入spring容器)

模拟一个实例工厂,创建业务层实现类 此工厂创建对象,必须现有工厂实例对象,再调用方法


public class InstanceFactory {
 public IAccountService createAccountService(){ 
    return new AccountServiceImpl(); 
   }
} 
<!-- 此种方式是:    先把工厂的创建交给 spring 来管理。   然后在使用工厂的 bean 来调用里面的方法
 factory-bean 属性:用于指定实例工厂 bean 的 id。   
 factory-method 属性:用于指定实例工厂中创建对象的方法。  --> 

<bean id="instancFactory" class="com.itheima.factory.InstanceFactory"></bean>
<bean id="accountService"      factory-bean="instancFactory"      factory-method="createAccountService"></bean

第三种:使用工厂中的静态方法创建对象(使用某个类中静态方法创建,并存入spring容器)

/** 
 * 模拟一个静态工厂,创建业务层实现类
 */
 public class StaticFactory {
     public static IAccountService createAccountService(){
           return new AccountServiceImpl();
    }
 } 
<!-- 此种方式是:   使用 StaticFactory 类中的静态方法 createAccountService 创建对象,并存入 spring 容器
   id 属性:指定 bean 的 id,用于从容器中获取   class 属性:指定静态工厂的全限定类名
   factory-method 属性:指定生产对象的静态方法  -->

<bean id="accountService"   class="com.itheima.factory.StaticFactory"    factory-method="createAccountService"> </bean> 

2 bean对象的作用范围
bean标签的scope属性,作用是指定bean的作用范围。
取值:(标粗常用)
singleton:单例(默认值)
prototype:多例

request:作用于web应用的请求范围
session:作用于web应用的会话范围
global-session:作用于集群环境会话范围(全局会话范围),当不是集群环境时 它就是session。

3 bean对象的声明周期
单例对象:scope="singleton" 一个应用只有一个对象的实例。
它的作用范围就是整个引用。
生命周期:
对象出生:当应用加载,创建容器时,对象就被创建了。
对象活着:只要容器在,对象一直活着。
对象死亡:当应用卸载,销毁容器时,对象就被销毁了。

多例对象:scope="prototype" 每次访问对象时,都会重新创建对象实例。
生命周期:
对象出生:当使用对象时,创建新的对象实例。
对象活着:只要对象在使用中,就一直活着。
对象死亡:当对象长时间不用时,被 java 的垃圾回收器回收了。

spring的依赖注入

依赖注入:Dependency Injection。它是 spring 框架核心 ioc 的具体实现。 我们的程序在编写时,通过控制反转,把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。 ioc 解耦只是降低他们的依赖关系,但不会消除。例如:我们的业务层仍会调用持久层的方法。 那这种业务层和持久层的依赖关系,在使用 spring 之后,就让 spring 来维护了。 简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。
依赖注入的方式有三种:
1使用构造函数提供
2 使用set方法提供
3 使用注解提供

构造函数注入 (此种方法不适合经常变化的数据)
顾名思义,就是使用类中的构造函数,给成员变量赋值。
优势:在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功。
弊端:改变了bean对象的实例化方式,使我们在创建对象时,如果我们用不到这些数据也必须提供。
注意,赋值的操作不是我们自己做的,而是通过配置的方式,让 spring 框架来为我们注入。
具体代码如下

   public class AccountServiceImpl implements IAccountService {
        private String name;
        private Integer age;
        private Date birthday;
     public AccountServiceImpl(String name, Integer age, Date birthday) {
       this.name = name;
       this.age = age;
       this.birthday = birthday;
  } 
 
 @Override
    public void saveAccount() {
       System.out.println(name+","+age+","+birthday);
     }
 } 

使用构造函数的方式,给 service 中的属性传值
要求: 类中需要提供一个对应参数列表的构造函数。
涉及的标签: <constructor-arg> </constructor-arg>
属性:
index:指定参数在构造函数参数列表的索引位置
type:指定参数在构造函数中的数据类型
name:指定参数在构造函数中的名称 用这个找给谁赋值 (常用)

上面三个都是找给谁赋值,下面两个指的是赋什么值的
value:它能赋的值是基本数据类型和 String 类型
ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean

 
 <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> 
 <constructor-arg name="name" value=" 张三 "></constructor-arg>  <constructor-arg name="age" value="18"></constructor-arg> 
 <constructor-arg name="birthday" ref="now"></constructor-arg> </bean> 
 
<bean id="now" class="java.util.Date"></bean> 


set 方法注入 (常用)

顾名思义,就是在类中提供需要注入成员的 set 方法。
优势:创建对象时 没有明确限制,可以使用默认构造函数。
弊端:如果有某个成员必须有值,则获取对象时set方法没有执行。

具体代码如下:

    public class AccountServiceImpl implements IAccountService { 
       private String name;
       private Integer age;  
       private Date birthday;

       public void setName(String name) {
           this.name = name; 
       }
      public void setAge(Integer age) { 
          this.age = age;  
       }
      public void setBirthday(Date birthday) {
          this.birthday = birthday; 
       } 
 
   @Override  
      public void saveAccount() {
         System.out.println(name+","+age+","+birthday); 
      }
   } 

通过配置文件给 bean 中的属性传值:
使用 set 方法的方式
涉及的标签: <property> </property>
属性:
name:找的是类中 set 方法的名称
ref:给属性赋值是其他 bean 类型的
value:给属性赋值是基本数据类型和 string 类型的 实际开发中,此种方式用的较多。

<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
   <property name="name" value="test"></property> 
   <property name="age" value="21"></property>
   <property name="birthday" ref="now"></property> 
</bean> <bean id="now" class="java.util.Date"></bean> 

注入集合属性

就是给类中的集合成员传值,它用的也是set方法注入的方式,只不过变量的数据类型都是集合。 我们这里介绍注入数组,List,Set,Map,Properties。具体代码如下:

public class AccountServiceImpl implements IAccountService {
      private String[] myStrs;
      private List<String> myList;
      private Set<String> mySet;
      private Map<String,String> myMap; 
     private Properties myProps; 

   public void setMyStrs(String[] myStrs) { 
        this.myStrs = myStrs; 
 }  
   public void setMyList(List<String> myList) {
       this.myList = myList; 
 } 
    public void setMySet(Set<String> mySet) { 
       this.mySet = mySet;
  }  
    public void setMyMap(Map<String, String> myMap) {
       this.myMap = myMap;
  }  
    public void setMyProps(Properties myProps) {
       this.myProps = myProps;
  } 
 
 @Override
    public void saveAccount() { 
      System.out.println(Arrays.toString(myStrs));
      System.out.println(myList);   
      System.out.println(mySet);
      System.out.println(myMap); 
      System.out.println(myProps);
    }
 } 

注入集合数据 List 结构的: array,list,set
Map 结构的 map,entry,props,prop

<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> 
 <!-- 在注入集合数据时,只要结构相同,标签可以互换 -->  <!-- 给数组注入数据 --> 
 <property name="myStrs"> 
      <set>
          <value>AAA</value>
          <value>BBB</value>
          <value>CCC</value>
      </set> 
 </property> 

 <!-- 注入 list 集合数据 -->
  <property name="myList"> 
    <array>
        <value>AAA</value>
        <value>BBB</value>
        <value>CCC</value>
       </array>
  </property> 

 <!-- 注入 set 集合数据 -->
  <property name="mySet"> 
  <list>
      <value>AAA</value>
      <value>BBB</value>
      <value>CCC</value>
     </list>
   </property> 
 
<!-- 注入 Map 数据 -->
  <property name="myMap">
   <props> 
   <prop key="testA">aaa</prop>
    <prop key="testB">bbb</prop>
   </props> 
 </property> 

 <!-- 注入 properties 数据 --> 
<property name="myProps"> 
  <map>
      <entry key="testA" value="aaa"></entry> 
     <entry key="testB">     
            <value>bbb</value> 
       </entry>
     </map>
  </property> 
</bean> 
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容