[notes]Spring 3.x应用开发实战——陈雄华 林开雄

来源:互联网 发布:新闻数据库表 编辑:程序博客网 时间:2024/05/20 19:17

6、AOP基础

OOP是竖切, AOP是横切
连接点:joinpoint, 程序执行的某个特定位置
切点:pointcut, 通过切点定位具体的连接点
增强:advice, 织入到目标类连接点上的一段程序代码
目标对象:target
引介:introduction
织入:weaving, 增加添加到连接点上的过程
Spring AOP使用两种代理机制:基于JDK的动态代理;基于CGLIB的动态代理。之所以需要两种,是因为JDK本身只提供接口的代理,不支持类的代理。
JDK动态代理:java.lang.reflect包下的Proxy, InvocationHandler
1.编写一个handler类实现InvocationHandler接口,invoke方法:
public Object invoke(Object target, Method method, Object[] args) throws Throwable {
//代理前逻辑
Object obj = methos.invoke(target, args);
//代理后逻辑
return obj;
}
2.调用Proxy,
Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);//三个参数classLoader, interfaces, 实现invocationHandler的类
GCLib动态代理:JDK的限制:只能为接口创建代理实例.
CGLib采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截技术拦截所有父类方法的调用,并顺势织入横切逻辑。
1、创建一个CGLibProxy实现MethodInterceptor
package com.billkang.springstudy;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class CGLibProxy implements MethodInterceptor {private Enhancer enhancer = new Enhancer();@SuppressWarnings("rawtypes")public Object getProxy(Class clazz) {enhancer.setSuperclass(clazz); //设置需要创建子类的类enhancer.setCallback(this);return enhancer.create(); //通过字节码技术动态创建子类实例}public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {System.out.println("代理前逻辑");Object result = proxy.invokeSuper(obj, args);System.out.println("代理后逻辑");return result;}}
2、应用的时候 ForumServiceImpl service = (ForumServiceImpl)cgLibProxy.getProxy(ForumServcieImpl.class);
由于CGlib采用动态创建子类的方式生成代理对象,所以不能对目标类中的final、private方法进行代理。
对于singleton的代理,推荐使用CGlib,对于其他作用域的代理,最好使用JDK,因为CGlib创建代理的时候慢,而创建出的代理对象运动效率极高,而使用JDK代理的表现刚好相反。
Spring切点检查:在创建代理时对目标类的每个连接点使用静态切点检查,如果仅通过静态切点检查就可以知道连接点是不匹配的,则不再进行动态切点检查;如果静态切点检查是匹配的,在运行时才进行动态切点检查。
静态切点检查只执行一次,动态切点检查每次运行都会执行。
Spring只能在方法级别上织入增强,Spring提供了4种类型的方法增强,分别是前置增强、后置增强、环绕增强和异常抛出增强,此外还有一种特殊的引介增强,引介增强是类级别的,它为目标类织入新的接口实现。从广义上说,增强其实就是一种最简单的切面,它既包括横切代码也包括切点信息,只不过它的切点只是简单的方法相对位置的信息,所以增强一般需要和切点联合才可以表示一个更具实用性的切面。
7、基于@AspectJ和Schema的AOP
package com.billkang.springstudy;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * @author binkang * @date May 1, 2017 */@Retention(RetentionPolicy.RUNTIME) //声明注解的保留期限@Target(ElementType.METHOD) //声明可以使用该注解的目标类型public @interface AnnotationTest { //定义注解@interfaceboolean value() default true; //声明注解成员}
注解成员的声明限制:
1)成员以无入参无抛出异常的方式声明,boolean value(String str),boolean value() throws Exception等都是非法的。
2)可以通过default为成员指定一个默认值,也可以不指定
3)成员类型是受限的,合法的类型包括原始类型及其封装类、String,Class,enums,注解类型,以及上述类型的数组类型。 ForumService value(),List foo()是非法的。
如果注解只有一个成员,则成员名必须是value(),在使用时可以忽略成员名和赋值号=,如@AnnotationTest(true). 注解可以没有成员,没有成员的注解称为标识注解,解释程序以标识注解存在与否进行相应的处理;此外,所有的注解类都隐式继承于java.lang.annotation.Annotation,但注解不允许显式继承于其他的接口。
@AspectJ采用注解来描述切点、增强,
使用哪种切面的选择:如果项目采用JDK5.0,可以优先考虑使用@AspectJ,如果项目只能使用低版本的JDK,则可以考虑使用<aop:aspect>;如果正在升级一个基于低版本Spring AOP开发的项目,则可以考虑使用<aop:advisor>复用已经存在的advisor类;如果项目只能使用低版本的Spring,那么就只能使用Advisor了。此外,值得注意的是一些切面只能使用基于API的Advisor方式进行构建,如基于ControlFlowPointcut的流程切面。
除了运行期织入切面的方式外,还可以在类加载期通过字节码编辑的技术,将切面织入到目标类中,这种织入方式称为LTW(Load Time Weaving).
8、Srping对DAO的支持
Spring 将数据访问流程划分为固定和变化两部分,并以模板的方式定义好流程,用回调接口将变化的部分开放出来,留给开发者自行定义。Spring为了进一步简化模板类的使用,为各种持久化技术提供了便捷的支持类,支持类不但包含数据访问模板,还包含数据源或会话等内容。通过扩展支持类定义自己的数据访问类是最简单的数据访问方式。
9、Spring事务管理
编程式事务需要你在代码中直接加入处理事务的逻辑,可能需要在代码中显式调用beginTransaction()、commit()、rollback()等事务管理相关的方法,如在执行a方法时候需要事务处理,你需要在a方法开始时候开启事务,处理完后。在方法结束时候,关闭事务.
声明式的事务的做法是在a方法外围添加注解或者直接在配置文件中定义,a方法需要事务处理,在spring中会通过配置文件在a方法前后拦截,并添加事务
事务4个特性:ACID Atomic原子性,Consistency一致性、Isolation隔离性、Durability持久性。
事务并发的问题:脏读、不可重复读、幻象读、每一类丢失更新、第二类丢失更新。
数据库锁机制:
行共享锁定
行独占锁定
表共享锁定
表共享行独占
表独占
4类隔离级别:
读不可提交、读可提交、可重复读、序列化
事务7类传播行为:
required: 使用当前事务,如果没有就新建
requres_new:新建一个事务,如果当前有事务就将当前事务挂起;
support: 支持当前事务,如果当前没有事务就以非事务方式执行;
mandatory: 使用当前事务,如果当前没有事务就抛异常
not support: 以非事务方式执行,如果当前有事务就挂起
never: 以非事务方式执行,如果当前有事务就抛异常
nested:如果当前存在事务就嵌套在事务内,如果当前没事务就执行required类似的操作
事务的传播行为。
14、使用OXM进行xml映射
Object XML Mapping
XStream别名:
类别名
类成员别名
类成员作为属性别名
XStream转换器:
implements Converter#
canConver(),//判断要转换的类型
marshal()//XML-->java
unmarshal()//java-->XML
XStream注解:
@XStreamAlias("user")
@XStreamAsAtribute
@XStreamConverter(DateConverter.class)
@XStreamImplict //隐式集合
@XStreamOmiField //忽略字段
应用的时候:
static {
xstream.processAnnotations(User.class);//
xstream.autodetectAnnotations(true);
}
流化对象:
xsteam.createObjectOutputStream(prettyPrintWriter);//objectToXML
xstream.creatObjectInputStream(bufferedReader);//XMLToObject
15、Spring MVC
initStrategies();
protected void initStrategies(ApplicationContext context) {
    initMultipartResolver();
    initLocaleResolver();
    initThemeResolver();
    initHandlerMappings();
    initHandlerAdapters();
    initHandlerExceptionResolvers();
    initRequestToViewNameTranslator();
    initViewResolvers();
}
initStratigies()方法在WebApplicationContext初始化后自动执行。
DispatcherServlet初始化后,会自动扫描上下文的Bean,根据名称或类型匹配的机制查找自定义的组件,找不到时则使用DispatcherServlet.properties定义的默认组件。

<context:component-scan base-package="com.baobaotao.web"/>
@Controller
@RequestMapping("/uer")  value,metod,params,headers

方法返回的字符串代表逻辑视图名。
返回ModelAndView

@RequestParam
@CookieValue
@RequestHeeader

HttpMessageConverter<T>
    AnnotationMetodHandlerAdapter默认已经封装了以下的HttpMessageConverter:
    StringHttpMessageConverter
    ByteArrayHttpMessageConverter
    SourceHttpMessageConverter
    XmlAwareFormHttpMessageConverter
    
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" p:messageConverters-ref=“messageConverters"/>
自定义的messageConverters-ref将覆盖默认的

响应消息的格式,通过请求消息头“Content-Type”及“Accept”属性确定。
    HttpHeaders entityHeaders = new HttpHeaders();
    entityHeaders.setContentType(MediaType.valueOf("application/json;UTF-8"));
    entityHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
    HttpEntity<User> requestEntity = new HttpEntity<User>(user, entityHeaders);
    
处理方法入参最多只能使用一个Spring MVC的注解,如使用了@ModelAttribute,就不能再使用@RequestParamore或@CookieValue。如果使用了两个注解,Spring MVC将抛出异常

Spring MVC一旦发现处理方法有Map或Model类型的入参,就会将请求内的隐含模型对象传递给这些参数。

@SessionAttributes

数据绑定:DataBinder
    数据转换:
        ConversionService,参考宿主类的上下文,并利用这些信息进行类型转换。
        @InitBinder,自定义编辑器
        WebBindingInitializer,装配在全局范围内使用的编辑器。
    数据格式化:
        Formatter<T>接口扩展于Printer<T> Parser<T>
        
视图解析器:
ViewResolver
    View resolveViewName(String viewName, Locale locale);

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/views/" p:suffix=".jsp" />

InternalResourceIvewResolver默认使用InternalResourceView作为视图实现类。

模板视图:
FreeMarker

本地化解析:
报文头的Accept-language
Srping 提供了四种本地化解析(local resolver):
    AcceptHeaderLocaleResolver:(Spring默认采用)
    CookieLocaleResolver
    SessionLocaleResolver
    LocaleChangeInteceptor

文件上传:
MultipartResolver
    CommonsMultipartResolver
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" 
    p:defaultEncoding="UTF-8"
    p:maxUplodaSize="5242800"
    p:uplodaTempDir="uploda/temp" />
    defaultEncoding必须和JSP的pageEncoding一致,uplodaTempDir 文件上传完成后,临时目录里的文件会被自动清除。
    
    有上传文件操作,表单的编码类型必须是:"multipart/form-data",即 <form enctype="multipart/form-data" />
    
静态资源处理:
<mvc:default-servlet-handler/> 将静态资源的处理经由Spring MVC框架交回Web应用服务器处理
<mvc;resources/> Spring MVC自己处理静态资源,并添加一些有用的附加功能。
16、单元测试
单元测试
集成测试
功能测试
系统测试
@Before
@After
分别可以有多个方法添加这两个注解
都使用public void 修饰,不能带参数

未完待续。。。
0 0
原创粉丝点击