zoukankan      html  css  js  c++  java
  • Senventh Week(补充完整)

    The Seventh Week: 8th April, 10th April

    Blog:

    1. Java Design Pattern (2)

    (1) Factory (Spring Bean Creation)

    (2) Singleton

    (3) Prototype

    (4) Proxy (Example in AOP)

    1.AOP的作用

      在OOP中,正是这种分散在各处且与对象核心功能无关的代码(横切代码)的存在,使得模块复用难度增加。AOP则将封装好的对象剖开,找出其中对多个对象产生影响的公共行为,并将其封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),切面将那些与业务无关,却被业务模块共同调用的逻辑提取并封装起来,减少了系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。

    2.DI 和 IOC 概念

      依赖注入或控制反转的定义中,调用者不负责被调用者的实例创建工作,该工作由Spring框架中的容器来负责,它通过开发者的配置来判断实例类型,创建后再注入调用者。由于Spring容器负责被调用者实例,实例创建后又负责将该实例注入调用者,因此称为依赖注入。而被调用者的实例创建工作不再由调用者来创建而是由Spring来创建,控制权由应用代码转移到了外部容器,控制权发生了反转,因此称为控制反转。

    3.BeanFactory与ApplicationContext

      ApplicationContext是BeanFactory的子接口,也被称为应用上下文。BeanFactory提供了Spring的配置框架和基本功能,ApplicationContext则添加了更多企业级功能(如国际化的支持),他另一重要优势在于当ApplicationContext容器初始化完成后,容器中所有的 singleton Bean 也都被实例化了,也就是说当你需要使用singleton Bean 是,在应用中无需等待就可以用,而其他BeanFactory接口的实现类,则会延迟到调用 getBean()方法时构造,ApplicationContext的初始化时间会稍长些,调用getBean()是由于Bean已经构造完毕,速度会更快。因此大部分系统都使用ApplicationContext,而只在资源较少的情况下,才考虑使用BeanFactory。

    4.AOP的实现策略

    (1)Java SE动态代理:
        使用动态代理可以为一个或多个接口在运行期动态生成实现对象,生成的对象中实现接口的方法时可以添加增强代码,从而实现AOP。缺点是只能针对接口进行代理,另外由于动态代理是通过反射实现的,有时可能要考虑反射调用的开销。
    (2)字节码生成(CGLib 动态代理)
        动态字节码生成技术是指在运行时动态生成指定类的一个子类对象,并覆盖其中特定方法,覆盖方法时可以添加增强代码,从而实现AOP。其常用工具是cglib。
    (3)定制的类加载器
        当需要对类的所有对象都添加增强,动态代理和字节码生成本质上都需要动态构造代理对象,即最终被增强的对象是由AOP框架生成,不是开发者new出来的。解决的办法就是实现自定义的类加载器,在一个类被加载时对其进行增强。JBoss就是采用这种方式实现AOP功能。
    (4)代码生成
        利用工具在已有代码基础上生成新的代码,其中可以添加任何横切代码来实现AOP。
    (5)语言扩展
        可以对构造方法和属性的赋值操作进行增强,AspectJ是采用这种方式实现AOP的一个常见Java语言扩展。

    核心概念

    1、横切关注点

    对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点

    2、切面(aspect)

    类是对物体特征的抽象,切面就是对横切关注点的抽象

    3、连接点(joinpoint)

    被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器

    4、切入点(pointcut)

    对连接点进行拦截的定义

    5、通知(advice)

    所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类

    6、目标对象

    代理的目标对象

    7、织入(weave)

    将切面应用到目标对象并导致代理对象创建的过程

    8、引入(introduction)

    在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

    Spring对AOP的支持

    Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它bean实例作为目标,这种关系可由IOC容器的依赖注入提供。Spring创建代理的规则为:

    1、默认使用Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了

    2、当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB

    AOP编程其实是很简单的事情,纵观AOP编程,程序员只需要参与三个部分:

    1、定义普通业务组件

    2、定义切入点,一个切入点可能横切多个业务组件

    3、定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作

    所以进行AOP编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP框架将自动生成AOP代理,即:代理对象的方法=增强处理+被代理对象的方法。

    2. CDI Features

    (1) EL(&SpEL)

    (2) Decorator

    (3) Interceptor

    (4) Producer

    Optional:

    (5) Scope

    (6) EventModel

    一、EL
    1.概述;
    EL是JSP内置的表达式语言,用以访问页面的上下文以及不同作用域中的对象 ,
    取得对象属性的值,或执行简单的运算或判断操作。EL在得到某个数据时,会自动进行数据类型的转换。
    使用EL表达式输出数据时,如果有则输出数据,如果为null则什么也不输出。
    2.语法:

    • EL表达式总是放在{}中,而且前边有一个:
    • {}
    • 获取对象的属性值可以直接通过“对象.属性名”:${user.name};

      注意:这里的属性名是get和set方法对应的属性值,并不是对象中的变量名。

    • 获取对象的属性也可以通过“对象[“属性名”]”:${user["name"]}
    • 获取Map中属性时可以以直接通过属性的key:({map.key},){map[key]}
    • 在指定域中获取属性:
      在EL表达式中如果我们直接使用属性名如:user<code>pageScoperequestScopesessionScopeapplicationScope</code><code>
    • { pageScope .user }:当前页面
      ({requestScope.user}</code>:当前请求 <code>){sessionScope.user}:当前会话
      ${sessionScope.user}:当前应用
      3.EL中包含11个隐含对象,这些对象可以在EL表达式中直接使用:
    • pageContext,和JSP中的pageContext功能一样

    • 请求域:pageScope/requestScope/sessionScope/applicationScope
    • 请求参数,参数对象主要用于获取get或post请求中的参数:
      param:获取指定的请求参数,({param.username}</code> paramValues:获取请求参数数组,如:<code>){paramValues.sport[1]}
    • 其他:header/headerValues/initParam/cookie

    3.EL中包含11个隐含对象,这些对象可以在EL表达式中直接使用:

    • pageContext,和JSP中的pageContext功能一样
    • 请求域:pageScope/requestScope/sessionScope/applicationScope
    • 请求参数,参数对象主要用于获取get或post请求中的参数:
      • param:获取指定的请求参数,${param.username}
      • paramValues:获取请求参数数组,如:${paramValues.sport[1]}
    • 其他:header/headerValues/initParam/cookie

    4.EL支持数学运算和逻辑运算:

    • 加减乘除:${17+5} => 22
    • 取余%或mod:${17%5} => 2
    • 比较运算符>,<,==,!=,<=,>=,eq,ne,lt,gt,le,ge:3>5
    • {3 gt 5} =>false
    • 逻辑比较 &&或and,!或not,||或or,empty:${!true} => false
       

    二、SpEL

    1)Spring框架的表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言。
    SpEL 为 bean 的属性进行动态赋值提供了便利.

    2)语法:SpEL 使用 #{…} 作为定界符,所有在大框号中的字符都将被认为是 SpEL。


    3)运用范围:

    • a. 对 bean 进行引用,调用属性值:#{book.name}
    • b.调用方法以及引用对象中的属性
      • 引用方法:#{dog.run()},引用静态方法:#{T(java.lang.Math).PI}
      • 引用对象的属性:#{user.name}
    • c.计算表达式的值
      • 加减乘除:#{counter.total + 40},#{T(java.lang.Math).PI * 2}
      • 加号作为字符串连接符:#{user.name + ‘ ‘ + user.address}
      • 比较运算符(>,<,=,>=,<=,==,lt,gt,eq,le,ge):
      • #{counter.total == 100},#{counter.total le 1000}
      • if-else条件判断,三元运算符:
      • #{user.name==‘Tom‘ ? ‘Jess‘}
    • d.正则表达式的匹配(matches)
      • #{user.name matches ‘^[a-zA-Z0-9_-]{4,16}$‘}
    • e.字面量的表示:
      • #{5},#{89.7},#{1e4},#{false}
      • 可使用单/双引号作为字符串表达符号:#{‘Chuck‘},#{"Chuck"}

    三、Decorator:

    1.Decorator 设计模式的特点:

    Decorator 设计模式正如毛胚房的装修,不会改变原毛胚房的基本框架,只是增加新的外观、功能等,且随着时间的推移,可以不断的实施装修工程:增加新的家具、根据心情换换新鲜的墙纸等等。在面向对象的程序设计中,扩展系统的原有功能也可以采用继承、组合的方式。继承也不会改变毛胚房(父类),但是由于装修工程的复杂和很多不可预测的改变,比如不同墙纸和地板样式的组合数量简直无法想想,难道我们要为每一种组合都定义一个子类吗?显然这是不现实的,即通过继承的方式来应对未来的功能和外观改变通常是吃力不讨好的事情。组合的方式也不可取,因为这要求不断的修改父类的结构,相当于对毛胚房大动干戈,房屋的可维护性和可靠性就大大降低了。

    让我们回顾一下设计模式的重要原则:Classes should be open for extenstion, but closed for modification。Decorator 设计模式很好的诠释了这个原则。

    2.CDI 对 Decorator 设计模式的支持:

    Decorator 设计模式虽然降低了需求变更对软件开发的影响,但是通过层层包装,即层层 new 操作创建对象的方式不够优雅。CDI 容器可以管理组件的生命周期,在大部分情况下我们无须通过 new 操作创建所需要的对象。CDI 中的 Decorator/Delegate 注解很大程度上简化了 Decorator 设计模式的代码编写量,比如实现上面相同的功能,借助于 CDI,就无须 RoomDecorator 这个抽象类了,所有的 Decorator 类直接实现 Room 接口并使用注解声明为 Decorator 即可

    3.总结:

    Decorator 设计模式简单而精巧,它其实是 Unix 哲学的体现:每一个应用程序都尽力做好自己,然后通过应用程序之间的协作完成更复杂的任务,正如 shell 的管道符的作用。从复杂应用程序框架设计的角度看,Decorator 设计模式也降低了模块之间的耦合度,而 CDI 更进了一步,借助于容器和类型安全的组件模型,简化了 Decorator 模式的应用,同时消除了某些潜在的运行时异常,也就是说,CDI 之上的 Decorator 设计模式能够帮助构建更加安全的复杂应用。

    四、Interceptor

    1.拦截器综述:

    拦截器的功能是定义在Java拦截器规范。

    拦截器规范定义了三种拦截点:

    • 业务方法拦截,
    • 生命周期回调侦听,
    • 超时拦截(EJB)方法。

    五、Producer

    CDI是为解耦而生.如Spring主要用途是AOP.IOC(DI),而CDI除了DI外,AOP功能也是有的.从实际使用上来看,CDI比Spring功能更丰富,更灵活,其代价也是有的,学习成本相对spring较高.

    1.CDI致力于松耦合,强类型.

    实现松散耦合的三种方式:

    • 部署时候的多态选择,@alternatives
    • producer methods在运行时的多态.
    • 上下文相关的生命周期管理与bean生命周期解耦。

    这些技术使客户端和服务器的松散耦合服务。客户端不再是紧密地绑定到一个接口的一个实现,也不需要管理生命周期实现。这种方法允许有状态的对象当作服务交互。松散耦合使系统更具活力。在以前,框架总是牺牲了类型安全(尤其是通过使用XML描述符,Spring2.5)。

    CDI提供了三个额外的重要措施,进一步松耦合:

    • 在业务逻辑层用拦截器技术解耦.
    • 修饰符(注解)可以用来分离一些业务问题
    • 用CDI EVENT技术进行解耦事件生产者与消费者.
  • 相关阅读:
    vue项目页面空白
    vue使用nprogress页面加载进度条
    如何让一个div居于页面正中间
    Django项目使用七牛云存储图片
    Celery ValueError: not enough values to unpack (expected 3, got 0)的解决方案
    网站ico那点事儿
    SpringBoot2.0 + SpringCloud Eureka搭建高可用注册中心(Eureka之三)
    SpringBoot2.0+SpringCloud Eureka构建服务治理(Eureka之一)
    SpringBoot2.0+SpringCloud Eureka搭建高可用注册中心(Eureka之二)
    Synchronized重入锁
  • 原文地址:https://www.cnblogs.com/fengzimu/p/10714832.html
Copyright © 2011-2022 走看看