重学Spring——IOC

1、IOC控制反转:控制什么?反转什么?
     控制:指选择接口的实现类控制权
     反转:指把这种控制权从代码中移除交由spring容器管理
2、IOC的类型
     1)、构造器注入

public class ConstructorInjection{
    private InterfaceClass interClazz;
    public ConstructorInjection(InterfaceClass interClazz){
        this.interClzaa = interClazz;
    }
    public void yourMethod(){
        interClzaa.someMethod();
    }
}

     2)、属性注入(也有叫get、set注入)

public class FieldsInjection{
    private InterfaceClass interClazz;
    public void setInterClazz(InterfaceClass interClazz){
        this.interClzaa = interClazz;
    }
    public void yourMethod(){
        interClzaa.someMethod();
    }
}

     3、通过容器完成IOC;在applicationContext.xml中配置,代码片段如下

<bean id="interClazz" class="ImplClass" />
<bean id="fieldsInjection" class="FieldsInjection" p:interClazz-ref="interClazz" />

4、IOC原理
     1)、简单示例:通过反射机制对实例化一个类

package com.keivndai.comomtest;

public class Car {
    private String brand;
    private String color;
    private int maxSpeed;
    //无参构造函数
    public Car() {
    }
    //有参构造函数
    public Car(String brand, String color, int maxSpeed) {
        this.brand = brand;
        this.color = color;
        this.maxSpeed = maxSpeed;
    }
    //篇幅问题,此处get、set方法省略
}
package com.keivndai.comomtest;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ReflectTest {
    public static Car initByDefaultConst() throws Exception{
        //通过类加载器加载Car
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        Class<?> clazz = loader.loadClass("com.keivndai.comomtest.Car");
        //获取默认的构造函数,实例化Car
        Constructor<?> cons = clazz.getConstructor((Class[])null);
        Car car = (Car)cons.newInstance();

        //通过反射机制赋值
        Method setBrand = clazz.getMethod("setBrand", String.class);
        setBrand.invoke(car, "benz");
        Method setColor = clazz.getMethod("setColor", String.class);
        setColor.invoke(car, "black");
        //此处只能用int不能用Integer;应该与方法中参数类型一致
        Method setMaxSpeed = clazz.getMethod("setMaxSpeed", int.class);
        setMaxSpeed.invoke(car, 250);

        return car;
    }

    public static void main(String[] args) throws Exception {
        Car car = ReflectTest.initByDefaultConst();
        car.introduce();
        //输出Car [brand=benz, color=black, maxSpeed=250]
    }
}

补充知识点:
1、类装载器ClassLoader的工作机制:类装载器就是寻找类的字节码文件并在JVM中的构造类的对象组件
     类装载器把一个类装入JVM要经过以下步骤
          1)、装载:查找和导入Class文件
          2)、校验:检查载入Class文件数据的正确性
          3)、准备:给类的静态变量分配空间
          4)、解析:将符号引用转成直接引用(可选,通过)
          5)、初始化:对类的静态变量、静态代码块执行初始化(这里又能引出问题java类的初始化顺序,这里有java类的初始化顺序)
     类文件被装载以后,在JVM中拥有一个类描述对象,该类的所有实例都拥有指向这个类描述对象的引用,而该类描述对象又拥有指向关联ClassLoader的引用.关系如下图(其实我可以画的更准确、更细致,但麻烦将就一下)
ClassLoader装载类关系图
2、java反射机制
     反射机制最主要有三个反射类Constructor、Method、Fields(在java.reflect包中).通过反射机制能够访问到私有属性、方法,demo如下
     ps.这里有个地方我本来掌握的不准确,这次复习了解了
        原来写一个通过属性名给属性赋值的功能时,知道fieldName之后我是先拉拼接setFiled,再通过反射获取setField方法,再使用setFiled.invoke(obj,value)来给filed赋值;其实通过fieldName获取Field,再filed.set(obj,value)即可,代码更简单清爽

package com.keivndai.comomtest;

public class PrivateCar {
    private String color;
    protected void drive(){
        System.out.println("drive my " +  color + " car!");
    }

}
package com.keivndai.comomtest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
 * 这个demo的关键之处在于,通过反射机制能够访问私有的方法、属性
* @ClassName: PrivateCarReflect
* @author kevindai
* @date 2016-8-17 下午10:28:12
*
 */
public class PrivateCarReflect {
    public static void main(String[] args) throws Exception {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        Class<?> clazz = cl.loadClass("com.keivndai.comomtest.PrivateCar");
        PrivateCar privateCar = (PrivateCar) clazz.newInstance();

        Field field = clazz.getDeclaredField("color");
        field.setAccessible(true);
        field.set(privateCar, "red");

        Method method = clazz.getDeclaredMethod("drive");
        method.setAccessible(true);
        method.invoke(privateCar);
        //输出:drive my red car!
    }
}

3、资源抽象接口Resource
访问Resource资源能使用的前缀

  • ps:web工程中classpath指web-inf/classes文件夹
    • ”classpath:”:只会在第一个加载的com.xxx.xxx包下查找
    • “classpath*”:会扫描到所有这些jar包及类路径下出现的com.xxx.xxx类路径
      • 如:有个名为kevindai的应用共分为3个模块,每个模块都有一个配置文件,分别为module1.xml、module2.xml、module3.xml,都入在com.kevindai目录下,每个模块单独打包,这时使用”classpath:com/kevindai/module*.xml”只会加载第一个模块的配置文件;而使用”classpath*:com/kevindai/module*.xml”则会加载三个模块的配置文件
    • pps.这里使用的*为Ant风格资源地址匹配符;有以下几种
      • ?:匹配文件名中一个字符(如:classpath*:com/kevindai/mod?le.xml)
      • :匹配文件名中任意个字符(如:classpath:com/kevindai/mod*.xml)
      • :匹配多层路径(如:classpath:com//mod*.xml)

5、spring Bean的配置文件

  • 基于xml配置:<bean id=”test” class=”com.kevindai.Test”/>
  • 适合场景:
    • bean来源于第三方库,如dataSource,JdbcTemplate,因无法使用注解,因此通过xml配置较好
    • 命名空间配置 ,如aop、context等,只能采用xml配置
  • 基于注解配置:@Compoent以及衍生的@Service、@Controller、@Repository
    • 适合场景:Bean的实现类是在当前项目中开发的
  • 基于java类配置:@Configuration
    • 适合场景:优势在于可以通过代码方式控制bean初始化整体逻辑;因此适合实例化复杂的bean
  • 其它零碎点
    • @Autowire spring提供,默认byType,可以设置为可为Null,如果重名则启动报错(最强大)
    • @Resource j2EE提供,默认byName,不能为Null
    • @Injec j2EE提供,基本与@Autowire一致,不能为Null
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值