DAY05-Sping02

作者: 建国同学 | 来源:发表于2020-04-27 11:23 被阅读0次

    一、 DI 注解

    • Spring的@Autowired
    • JavaEE的@Resource

    都是取代注入bean, 贴类中setter 方法或者字段上(完成属性或字段的注入,注入是 bean,取代 XML property ref 元素)

    1. 可以让 Spring 自动的把属性或字段需要的对象找出来,并注入到属性上或字段上。
    2. 可以贴在字段或者 setter 方法上面。

    二、 IoC 注解

    让Spring简化配置bean


    • 四个注解的功能是相同的,用来让Spring帮我们创建对象,只是用于标注不同类型的类上。
      @Repository:用于标注数据访问组件,即DAO实现类上。
      @Service:用于标注业务层实现类上。
      @Controller:用于标注控制层类上(如SpringMVC的Controller)。
      @Component:当不是以上的话,可以使用这个注解进行标注。

    在 spring 配置文件中配置第三方解析程序 <context:component-scan base-package="使用上面这些注解的类所在包"/>


    image.png

    注意:@Component 不写 value 值的话,bean 名字就类名首字母小写,上面列子就是 bean 的名字就是 person。

    三、 bean的作用域、初始化、销毁注解

    @Scope: 贴在类上,标明 bean 的作用域。
    @PostConstruct: 贴在方法上,标明 bean 创建完后调用此方法。
    @PreDestroy : 贴在方法上,标明容器销毁时调用此方法。


    四、 applicationContext.xml

    image.png

    五、 代理模式

    解决事务的繁琐

    • 客户端直接使用的都是代理对象,不知道真实对象是谁,此时代理对象可以在客户端和真实对象之间起到中介的作用。
    1. 代理对象完全包含真实对象,客户端使用的都是代理对象的方法,和真实对象没有直接关系;
    2. 代理模式的职责:把不是真实对象该做的事情从真实对象上撇开—职责分离。

    分类

    • 静态代理:在程序运行前就已经存在代理类的字节码文件,代理对象和真实对象的关系在运行前就确定了。(即代理类及对象要我们自己创建)
    • 动态代理:代理类是在程序运行期间由JVM通过反射等机制动态的生成的,所以不存在代理类的字节码文件,动态生成字节码对象,代理对象和真实对象的关系是在程序运行时期才确定的。(即代理类及对象不要我们自己创建)
      动态代理实现方式:
      1.针对真实类有接口使用 JDK 动态代理;
      2.针对真实类没实现接口使用CGLIB或Javassist组件。

    六、静态代理

    • 解决代码责任不分离的问题,真实对象隐藏起来了,保护真实对象。(不在容器里了)
      缺点:项目的变大,代理类太多



    七、JDK动态代理

    • 解决静态代理的问题,不需手动地提供那么多代理类
      缺点:api难用,配置Spring麻烦

    动态代理API

    - java.lang.reflect.Proxy类
    Java 动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。 
    主要方法:public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler hanlder)
    方法职责:为指定类加载器、一组接口及调用处理器生成动态代理类实例 
    参数:   
            loader :类加载器,一般传递真实对象的类加载器   
            interfaces:代理类需要实现的接口  
            handler:代理执行处理器,说人话就是生成代理对象帮你要做什么
    返回:创建的代理对象
    
    - java.lang.reflect.InvocationHandler 接口
    主要方法:public Object invoke(Object proxy, Method method, Object[] args)
        方法职责:负责集中处理动态代理类上的所有方法调用,让使用者自定义做什么事情,  对原来方法增强(加什么功能)。
        参数:
            proxy :生成的代理对象    
            method:当前调用的真实方法对象    
            args :当前调用方法的实参
        返回:真实方法的返回结果
    主要方法:public Object invoke(Object proxy, Method method, Object[] args)
        方法职责:负责集中处理动态代理类上的所有方法调用,让使用者自定义做什么事情,  对原来方法增强(加什么功能)。
        参数:
            proxy :生成的代理对象    
            method:当前调用的真实方法对象    
            args :当前调用方法的实参
        返回:真实方法的返回结果
    

    要使用 JDK 动态代理,真实类必须实现接口

    类体系及调用流程

    image.png

    八、CGLIB动态代理

    区别:与JDK动态代理不同的是,其真实类不用实现接口,生成代理类的代码不一样且代理类会继承真实类。

    动态代理API

    • org.springframework.cglib.proxy.Enhancer
      类似JDK中Proxy,用来生成代理类创建代理对象的。
    • org.springframework.cglib.proxy.InvocationHandler
      类似JDK中InvocationHandler,让使用者自定义做什么事情,对原来方法增强。

    实现

    • 修改 TransactionHandler 实现 org.springframework.cglib.proxy.InvocationHandler 接口


    • 修改单元测试类中的测试方法,改用 Enhancer 来生成代理类创建代理对象的


    类体系及调用流程

    image.png

    九、 动态代理选用

    • JDK 动态代理是基于实现接口的,CGLIB 和 Javassit 是基于继承委托类的。
      从性能上考虑:Javassit > CGLIB > JDK。
    • 若真实类实现了接口,优先选用 JDK 动态代理。(因为会产生更加松耦合的系统,也更符合面向接口编程)
    • 若真实类没有实现任何接口,使用 Javassit 和 CGLIB 动态代理。

    相关文章

      网友评论

        本文标题:DAY05-Sping02

        本文链接:https://www.haomeiwen.com/subject/ryxywhtx.html