Day1:Spring-IoC、DI

springIOC:控制反转
普通JAVA程序运行流程:

1、HelloWorld.java
public class HelloWorld{
    public void say(){
        System.out.println("hello");
    }

    public static void main(String[] args){
        HelloWorld hw = new HelloWorld();
        hw.say();
    }
}

2、.java ---> .class   javac excute

3、把.class文件放入到JVM中

4、得到运行结果
Spring容器运行:

1、完成HelloWorld.java

2、把HelloWorld这个类以配置文件形式放入到容器中

3、启动Spring容器

4、利用Spring的API把HelloWorld这个对象拿出来

5、HelloWorld.say()完成方法的调用

说明:创建HelloWorld这个类是由Spring容器完成,Spring容器就相当于生活中的电饭煲,而类就像是电饭煲中的米粒,对象就像是电饭煲中的饭粒。
Spring做了创建对象这个动作,因此"反转"一次的含义为Spring自动把类转换为现实中的对象,所以叫“控制反转”。
<!--把HelloWorld这个类纳入Spring容器中,通过在applicationContext.xml配置文件中创建bean对象,bean规范写法为:
id为bean的唯一标识,类的第一个字母变为小写,其余不变;
class为类的全名!-->
<bean id="helloworld" class="***.***.Hellworld"></bean>
启动Spring容器:

public class IOCTest{
       /**
         *创建Spring容器就相当于启动Spring容器
*Spring做的其中的一个工作就是创建对象
*/ @Test public void testHelloWorld(){ ApplicationContext context
= new ClassPathXmlApplicationContext("applicationContext"); HelloWorld helloWorld = context.getBean("helloWorld"); helloWorld.say(); } }

别名
<beans>
    <alias name="person" alias="p"/><!--name引用的是已经创建的bean-name,alias则是写不同于bean-name的名字,name的数量不限,相对于一个人的绰号不限-->
    <bean name="person" class="cn.itcast.aliasspring.Person"/>
</beans>
通过这样的配置,可以达到在一个地方命名,在多个地方使用不同的名字的效果。

Java创建对象有两种方式:1、new   2、反射机制
Bean创建对象方法有三种:1、构造函数 2、静态工厂 3、实例工厂
springIOC总结:
   *  spring容器中的bean创建
        *  三种方案   面试题
            *  利用默认的构造函数
            *  利用静态工厂方法
            *  利用实例工厂方法
        *  创建对象的时机
            *  默认情况下,在spring启动的时候,创建纳入spring容器中所有的bean
                  在spring容器启动的时候,可以检查错误
                  但是如果bean的属性中有数据,会过早的加载到内存中,所以如果bean中有数据
                  应该把数据的对象的声明放在方法中
            *  如果在spring的配置文件中,有lazy-init为true,则context.getBean("beanId")时才要创建对象
                  缺点:在spring容器启动的时候,是检验不出错误的
        *   对象的作用域
            *  在配置文件中,scope为
                  "singleton" 
                     *  默认值
                     *  spring产生的bean只有一个实例
                     *  处于单例模式的bean的创建、初始化、销毁都是受spring容器管理的
                     *  在容器关闭的时候执行销毁工作
                  "prototype"
                     *  多例
                     *  spring容器负责该bean的创建、初始化,但是销毁工作程序员做
                     *  无论该bean的lazy-init为什么值,都在context.getBean时创建对象
                     *  如果该bean中有资源对象,手动关闭
        *    init和destroy方法
               init在构造器执行完毕之后执行
               destroy方法在spring关闭的时候执行
DI-Dependency Injection 依赖注入
public class Person{
   private Long pid;
   private String pname;
   //调用set方法给属性赋值
   public void setPname(String pname){
       this.pname = pname;
   }
  //利用构造器可以给属性赋值
   public Person(String pname){
       this.pname = pname;
   }
DI可以翻译为怎样为这些类型赋值
public
class Person{ //基本数据类型 private String s; private Long age; //引用数据类型 private Student s; private List<Student>;//list类型 private Set<Student>://set类型 private Map private Properties property;//属性文件类型 }
DI依赖注入小总结:
* 依赖注入可以翻译为怎样为对象赋值
* 依赖注入主要有两种种途径
   |--使用构造器注入
       |--通过参数顺序注入
        <constructor-arg index="0">
              <value>张三</value>
        </constructor-arg>
        <constructor-arg index="1">
               <value>56</value>
         </constructor-arg> 
       |--通过参数类型注入
         <constructor-arg type="java.lang.Integer">
              <value>56</value>
         </constructor-arg>
         <constructor-arg type="java.lang.String">
               <value>张三</value>
          </constructor-arg>
   |--使用属性setting方法注入,要数据类型装备
       |--装配基本数据类型
           <bean id="personService"              class="****.PersonServiceImpl">
                <!-- 基本类型,string类型 -->
        <property name="age" value="20"></property>
        <property name="name" value="张无忌"></property>                                 </bean>

<bean id="person" class="com.itcast.bean.Person" />
          <bean id="personService"    class="com.itcast.bean.impl.PersonServiceImpl">
            <property name="person" ref<!--引用其他Bean字段-->="person" />
</bean>

       |--装配引用数据类型
           |--装配list集合
                   <property name="lists">
                          <list>
                                 <value>list1</value>
                                 <value>list2</value>
                                  <ref bean="person"/>
                          </list>
                     </property>
           |--装配set集合
                     <property name ="sets">
                           <set>
                                   <value>set1</value>
                                   <value>set2</value>
                                    <ref bean="person"/>
                            </set>
                        </property>
           |--装配map集合
                       <property name="maps">
                             <map>
                                    <entry key="01">
                                            <value> map01</value>
                                     </entry>
                                      <entry key="02">
                                               <value>map02</value>
                                      </entry>
                             </map>
                       </property>
           |--装配Properties  
                    <property name="props">
                       <props>
                         <prop key="01">prop1</prop>
                         <prop key="02">prop2</prop>
                       </props>
                    </property>  
                               
注解:
  *  用来标识的
   *  注解是用来标注类里的东西
   *  注解不能单独存在,只能依附于类中的结构

   *  jdk中经常用的几种注解:
       @Target
          ElementType
              TYPE  类和接口
              FIELD 属性
              METHOD 方法
              PACKAGE 包
PARAMETER 方法中的参数
CONSTRUCTOR 构造器
ANNOTATION_TYPE 注解类型 用于说明这个注解所标注的注解用在哪些地方 @Documented 是否出现在帮助文档 @Retention 作用范围 SOURCE 源代码 CLASS 源代码和class文件 RUNTIME 源代码、class文件、运行时
* 自定义注解 * 一个自定义注解必须有 @Target 说明这个注解标注在哪个部位 @Retention 说明注解的作用范围 * @interface 说明是一个注解类 * 注解类中可以有属性 String value(); * 注解解析器 用来解析标注在类上的注解

注入步骤:
A、在配置文件中,引入context命名空间
<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-2.5.xsd
http://www.springframework.org/schema/context                http://www.springframework.org/schema/context/spring-context-2.5.xsd">

B、在配置文件中加入context:annotation-config标签 <context:annotation-config/> 这个配置隐式注册了多个对注释进行解析处理的处理器 AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor, PersistenceAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor 注: @Resource注解在spring安装目录的libj2eecommon-annotations.jar
C、创建要扫描注解的Bean对象
工作原理:
   当spring容器启动的时候,
   ApplicationContext context = new ClassPathXmlApplicationContext("cn/itcast/spring0401/di/annotation/applicationContext.xml");
   spring容器会创建纳入spring容器管理的bean.分别为person和student; 
   spring容器会解析配置文件,会解析到<context:annotation-config>
   </context:annotation-config>,会在纳入spring的bean范围内查找属性上是否存在
   @Resource(name="student")
    * 如果存在:
    * 继续解析@Resource有没有name属性
    * 如果没有name属性就会在所属的属性上,把属性的名称解析出来。会让属性的名称和spring中的bean中的id进行匹配,如果匹配成功,则把spring容器中相应的对象赋值给该属性。如果匹配不成功,则按照类型进行匹配
    *  @Resource有name属性就会解析name属性的值,把这个值和spring容器中的bean的id进行匹配
    * 如果匹配成功,则把spring容器中的相应的对象赋值给该属性
    * 如果匹配不成功,则直接报错
                    
    * 如果不存在:不做任何事情
              
    xml和注解的写法:
    xml:书写比较麻烦,但是效率比较高
    注解:书写比较简单,但是效率比较低
       注解的写法只适合引用
Spring自己的注解注入类型:
@Autowired:@Autowired 默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配
@Qualifier:使用按名称装配,可以结合@Qualifier注解一起使用
@Resource: 名称可以通过@Resource的name属性指定,如果没有指定name属性,
•    当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象
•    当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。 

@PostConstruct:指定Bean的初始化方法
@PreDestroy:指定Bean的销毁方法
Spring注解自动扫描原理:
  *  类扫描的注解解析器包含了依赖注入的注解解析器
   *  原理:
   当启动spring容器的时候,
        ApplicationContext context = new ClassPathXmlApplicationContext("cn/itcast/spring0401/scan/applicationContext.xml");
   spring容器会加载配置文件,并且解析配置文件,就会解析到
   *   类扫描的注解解析器,会在base-package包及子包中扫描所有的类 
   *  检查类上是否有@Compontent注解
   *  如果有
   *  @Compontent是否有value属性
   *  没有value属性 则会把这个注解所在的类的类名的第一个字母变成小写,其余的不变当做bean的id
   *  如果有value属性 则value属性的值就是bean的id
   *  如果没有
   *   类扫描注解解析完以后,所有的在base-package包及子包下的带有@Compontent注解的类就被纳入spring管理了
   *   在纳入spring管理的类中扫描各个属性,看属性是否有@Resource,再根据这个注解的规则进行操作。
   *   扫描的次数:
   *  根据base-package包及子包进行扫描
   *  扫描纳入spring管理的所有的bean的属性
   *  属性的name的值和bean中的id进行匹配
<context:component-scan base-package="cn.vijayt"/>----->@Repository@Service@Controller
Spring继承:
在Spring中继承关系不能在JAVA类中建立,必须在Spring容器的配置文件中建立继承关系,利用parent="父类"来建立
原文地址:https://www.cnblogs.com/vijay/p/3525566.html