基础加强

学习目标

案例-自定义单元测试@MyTest

案例-全局的编码的解决

一、类加载器

1.什么是类加载器,作用是什么?

类加载器就加载字节码文件(.class)

2.类加载器的种类

类加载器有三种,不同类加载器加载不同的

1)BootStrap:引导类加载器:加载都是最基础的文件

2)ExtClassLoader:扩展类加载器:加载都是基础的文件

3)AppClassLoader:应用类加载器:三方jar包和自己编写java文件

怎么获得类加载器?(重点)

ClassLoader 字节码对象.getClassLoader();

public class Demo {

   public static void main(String[] args) {

      //获得Demo字节码文件的类加载器

      Class clazz = Demo.class;//获得Demo的字节码对象

      ClassLoader classLoader = clazz.getClassLoader();//获得类加载器

      //getResource的参数路径相对classes(src)

      //获得classes(src)下的任何的资源

      String path = classLoader.getResource("com/itheima/classloader/jdbc.properties").getPath();

      //classLoader.getResourceAsStream("");

      System.out.println(path);  

   }

}

二、注解 @xxx

1.什么是注解,注解作用

注解就是符合一定格式的语法 @xxxx

注解作用:

注释:在阅读程序时清楚----给程序员看的

注解:给jvm看的,给机器看的

注解在目前而言最主流的应用:代替配置文件

关于配置文件与注解开发的优缺点:

注解优点:开发效率高 成本低

注解缺点:耦合性大 并且不利于后期维护

企业的趋势:混合使用,不经常修改的可以用注解的形式。

2.jdk5提供的注解

@Override:告知编译器此方法是覆盖父类的

@Deprecated:标注过时

@SuppressWarnings:压制警告

deprecation,忽略过时

unused,忽略不使用

rawtypes,忽略类型安全

all,忽略所有

…..

发现的问题:

不同的注解只能在不同的位置使用(方法上、字段上、类上)

3.自定义注解(了解)

1)怎样去编写一个自定义的注解

2)怎样去使用注解

3)怎样去解析注解-----使用反射知识

(1)编写一个注解

关键字:@interface

注解的属性:

语法:返回值 名称();

注意:如果属性的名字是value,并且注解的属性值有一个 那么在使用注解时可以省略value

注解属性类型只能是以下几种

1.基本类型

2.String

3.枚举类型

4.注解类型

5.Class类型

6.以上类型的一维数组类型

(2)使用注解

在类/方法/字段 上面是@XXX

(3)解析使用了注解的类

介入一个概念:元注解:代表修饰注解的注解,作用:限制定义的注解的特性

@Retention

SOURCE: 注解在源码级别可见

CLASS:注解在字节码文件级别可见

RUNTIME:注解在整个运行阶段都可见

@Target

代表注解修饰的范围:类上使用,方法上使用,字段上使用

FIELD:字段上可用此注解

METHOD:方法上可以用此注解

TYPE:类/接口上可以使用此注解

注意:要想解析使用了注解的类 , 那么该注解的Retention必须设置成Runtime

关于注解解析的实质:从注解中解析出属性值

字节码对象存在于获得注解相关的方法

isAnnotationPresent(Class<? extends Annotation> annotationClass) 判断该字节码对象身上是否使用该注解了

getAnnotation(Class<A> annotationClass) :获得该字节码对象身上的注解对象

4.案例-自定义单元测试@MyTest

public class MyTestParster {

   public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {

      //获得TestDemo

      Class clazz = TestDemo.class;

      //获得所有的方法

      Method[] methods = clazz.getMethods();

      if(methods!=null){

         //获得注解使用了@MyTest的方法

         for(Method method:methods){

            //判断该方法是否使用了@MyTest注解

            boolean annotationPresent = method.isAnnotationPresent(MyTest.class);

            if(annotationPresent){

                //该方法使用MyTest注解了

                method.invoke(clazz.newInstance(), null);

            }

         }

      } 

   }

}

三、动态代理

1.什么是代理(中介)

目标对象/被代理对象 ------ 房主:真正的租房的方法

代理对象 ------- 黑中介:有租房子的方法(调用房主的租房的方法)

执行代理对象方法的对象 ---- 租房的人

流程:我们要租房----->中介(租房的方法)------>房主(租房的方法)

抽象:调用对象----->代理对象------>目标对象

2.动态代理

动态代理:不用手动编写一个代理对象,不需要一一编写与目标对象相同的方法,这个过程,在运行时 的内存中动态生成代理对象。------字节码对象级别的代理对象

动态代理的API:

在jdk的API中存在一个Proxy中存在一个生成动态代理的的方法newProxyInstance

static Object

newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

返回值:Object就是代理对象

参数:loader:代表与目标对象相同的类加载器-------目标对

象.getClass().getClassLoader()

interfaces:代表与目标对象实现的所有的接口字节码对象数组

h:具体的代理的操作,InvocationHandler接口

注意:JDK的Proxy方式实现的动态代理 目标对象必须有接口 没有接口不能实现jdk版动态代理

例子一:

public class ProxyTest {

   @Test

   public void test1(){

      //获得动态的代理对象----在运行时 在内存中动态的为Target创建一个虚拟的代理对象

      //objProxy是代理对象 根据参数确定到底是谁的代理对象

      TargetInterface objProxy = (TargetInterface) Proxy.newProxyInstance(

            Target.class.getClassLoader(), //与目标对象相同的类加载器

            new Class[]{TargetInterface.class},

            new InvocationHandler() {

                //invoke 代表的是执行代理对象的方法

                @Override

                //method:代表目标对象的方法字节码对象

                //args:代表目标对象的响应的方法的参数

                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                   System.out.println("目标方法前的逻辑");

                   //执行目标对象的方法

                   Object invoke = method.invoke(new Target(), args);

                   System.out.println("目标方法后的逻辑");

                   return invoke;

                }

            }

         );

      objProxy.method1();

      String method2 = objProxy.method2();

      System.out.println(method2);

   }

}

例子二:

public class ProxyTest2 {

   public static void main(String[] args) {

      final Target target = new Target();

      //动态创建代理对象

      TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(

            target.getClass().getClassLoader(),

            target.getClass().getInterfaces(),

            new InvocationHandler() {

                @Override

                //被执行几次?------- 看代理对象调用方法几次

                //代理对象调用接口相应方法 都是调用invoke

                /*

                 * proxy:是代理对象

                 * method:代表的是目标方法的字节码对象

                 * args:代表是调用目标方法时参数

                 */

                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                   //反射知识点

                   Object invoke = method.invoke(target, args);//目标对象的相应方法

                   //retrun返回的值给代理对象

                   return invoke;

                }

            }

         );

      proxy.method1();//调用invoke---Method:目标对象的method1方法  args:null  返回值null

      String method2 = proxy.method2();//调用invoke---Method:目标对象的method2方法  args:null  返回值method2

      int method3 = proxy.method3(100);////调用invoke-----Method:目标对象的method3方法 args:Object[]{100}  返回值100

      System.out.println(method2);

      System.out.println(method3);
}
}

3.案例-全局的编码的解决

public class EncodingFilter implements Filter{

   @Override

   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

         throws IOException, ServletException {

      final HttpServletRequest req = (HttpServletRequest) request;

      //使用动态代理完成全局编码

      HttpServletRequest enhanceRequset = (HttpServletRequest) Proxy.newProxyInstance(

            req.getClass().getClassLoader(),

            req.getClass().getInterfaces(),

            new InvocationHandler() {

                @Override

                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                   //对getParameter方法进行增强

                   String name = method.getName();//获得目标对象的方法名称

                   if("getParameter".equals(name)){

                      String invoke = (String) method.invoke(req, args);//乱码

                      //转码

                      invoke = new String(invoke.getBytes("iso8859-1"),"UTF-8");

                      return invoke;
} return method.invoke(req, args);
}
}
); chain.doFilter(enhanceRequset, response); //request.setCharacterEncoding("UTF-8"); //在传递request之前对request的getParameter方法进行增强 /* * 装饰者模式(包装) * * 1、增强类与被增强的类要实现统一接口 * 2、在增强类中传入被增强的类 * 3、需要增强的方法重写 不需要增强的方法调用被增强对象的 * */ //被增强的对象 //HttpServletRequest req = (HttpServletRequest) request; //增强对象 //EnhanceRequest enhanceRequest = new EnhanceRequest(req); //chain.doFilter(enhanceRequest, response); } @Override public void destroy() {
}
@Override public void init(FilterConfig filterConfig) throws ServletException {
}
} class EnhanceRequest extends HttpServletRequestWrapper{ private HttpServletRequest request; public EnhanceRequest(HttpServletRequest request) { super(request); this.request = request; } //对getParaameter增强 @Override public String getParameter(String name) { String parameter = request.getParameter(name);//乱码 try { parameter = new String(parameter.getBytes("iso8859-1"),"UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return parameter; } }

【JAVAWEB学习笔记】25_基础加强:类加载器、注解 @xxx和动态代理的更多相关文章

  1. Javaweb学习笔记——(二十八)——————Servlet3.0、动态代理、类加载器

    web最后一天:完了. Servlet3.0          一.要求         1.MyEclipse10.0或以上版本         2.发布到Tomcat7.0或以上版本 二.步骤   ...

  2. 【JVM学习笔记】线程上下文类加载器

    有许多地方能够看到线程上下文类加载的设置,比如在sun.misc.Launcher类的构造方法中,能够看到如下代码 先写一个例子建立感性认识 public class Test { public st ...

  3. 大数据之路week05--day07(序列化、类加载器、反射、动态代理)

    遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题 a,什么叫序列化和反序列化b,作用.为啥要实现这个 Serializable 接口,也就是为啥要序列化c,seri ...

  4. JavaWeb学习笔记——jsp基础语法

    1.JSP注释 显式注释 <!-- 注释内容 --> 隐式注释,隐式注释在客户端无法看见 // /* */ <% 注释内容 %> 2.Scriptlet(小脚本程序) 所有嵌入 ...

  5. JavaWeb学习笔记——JavaEE基础知识

  6. 《Java编程思想》学习笔记(二)——类加载及执行顺序

    <Java编程思想>学习笔记(二)--类加载及执行顺序 (这是很久之前写的,保存在印象笔记上,今天写在博客上.) 今天看Java编程思想,看到这样一道代码 //: OrderOfIniti ...

  7. MyBatis:学习笔记(1)——基础知识

    MyBatis:学习笔记(1)--基础知识 引入MyBatis JDBC编程的问题及解决设想 ☐ 数据库连接使用时创建,不使用时就释放,频繁开启和关闭,造成数据库资源浪费,影响数据库性能. ☐ 使用数 ...

  8. JavaWeb学习笔记总结 目录篇

    JavaWeb学习笔记一: XML解析 JavaWeb学习笔记二 Http协议和Tomcat服务器 JavaWeb学习笔记三 Servlet JavaWeb学习笔记四 request&resp ...

  9. Quartz学习笔记:基础知识

    Quartz学习笔记:基础知识 引入Quartz 关于任务调度 关于任务调度,Java.util.Timer是最简单的一种实现任务调度的方法,简单的使用如下: import java.util.Tim ...

随机推荐

  1. 转载linux c语言程序的Makefile编写

    对于程序设计员来说,makefile是我们绕不过去的一个坎.可能对于习惯Visual C++的用户来说,是否会编写makefile无所谓.毕竟工具本身已经帮我们做好了全部的编译流程.但是在Linux上 ...

  2. Windows下检测文件名大小写是否匹配

    跨平台开发有一个众所周知,但因为只是偶尔受到困扰,一般人不会在意的问题,就是windows对文件名大小写不敏感,而其他平台对文件名大小写敏感.因此可能出现在windows平台开发时一切正常,但部署/打 ...

  3. 在centOS7.2安装配置zabbix监控

    zabbix由两部分组成,zabbix-server与可选的zabbix-agent.zabbix-server可以通过SNMP,ZABBIX-AGENT,PING,端口监视等方法提供对远程服务器/网 ...

  4. 管中窥豹——从对象的生命周期梳理JVM内存结构、GC调优、类加载、AOP编程及性能监控

    如题,本文的宗旨既是透过对象的生命周期,来梳理JVM内存结构及GC相关知识,并辅以AOP及双亲委派机制原理,学习不仅仅是海绵式的吸收学习,还需要自己去分析why,加深对技术的理解和认知,祝大家早日走上 ...

  5. axure 动态面板制作图片轮播 (01图片轮播)

    利用Axure的动态面板组件制作图片轮播: 首先现在操作区添加一个动态面板组件: 鼠标放在动态面板上,右键单击选择面板状态管理,给动态面板设置名称并添加两条状态然后点击确定. 双击动态面板,然后双击s ...

  6. mui 页面间传值得2种方式

    通过最近得工作开发刚接触mui框架,用到了页面间得传值, 第一种:通过url进行传值 父页面代码: mui.openWindow({ id:'子页面.html', url:'子页面.html?para ...

  7. 111_climbing-stairs

    /*@Copyright:LintCode@Author:   Monster__li@Problem:  http://www.lintcode.com/problem/climbing-stair ...

  8. pixi.js

    添加基本文件(库文件) 渲染库 pixi.js pixi.lib.js是pixi.js的子集,依赖class.js,cat.js,event_emiter.js文件 pixi.scroller.js ...

  9. 《Vue2.0 实践揭秘》终于出版啦!

    不知不觉间在园子开博都两年多了,最近一些园友问最近去哪了为何都没有新的文章了.最近确实发生了很多的事,一是忙工作二就是忙着写书.这还得多些园子的小编,自两年前发表的"架构师修炼"系 ...

  10. EverythingAboutJava

    1 GC gabage collection 垃圾回收Java GC系列(1):Java垃圾回收简介 http://mp.weixin.qq.com/s?src=3&timestamp=149 ...