基础加强

学习目标

案例-自定义单元测试@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. 南京.NET线下活动后续—一对一技术交流

    4月1日星期六,发生了几件大事: 1.网民与老板花式斗图,庆祝愚人节. 2.国务院设立雄安新区,定为千年大计 3.纳龙科技的程序猿赴镇江斯诺物联科技进行一对一技术交流. 此次一对一交流活动是3月11日 ...

  2. 老李推荐:第6章6节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-命令队列

    老李推荐:第6章6节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-命令队列   事件源在获得字串命令并把它翻译成对应的MonkeyEvent事件后,会把这些 ...

  3. Angular.js学习笔记 (一)

    - angular中最重要的概念是指令(directive)- ng-model 是双向数据绑定的指令,效果就是将当前元素的value属性和模型中的[user.name]建立绑定关系### 模块(Mo ...

  4. php最新微信扫码在线支付接口。ecshop和shopex,shopnc下完美无错

    最近为客户的一个在线商城做了一个微信扫码在线支付的接口.跟大家分享一下. 1 首先可以模仿其他的接口,比如支付宝,财付通等的接口,构建模块功能文件和语言文件.2 微信提供2种扫码方式,大家可以根据自己 ...

  5. Ubuntu16.04安装NVIDIA驱动时的一些坑与解决方案

    这几天在新购置的笔记本上部署工作环境,在安装NVIDIA驱动的时候遇到了不少坑,重装了很多次,在Ubuntu论坛以及其他资料源看了很多大牛的分析,最终终于解决了一个又一个问题,过程比较艰辛,所以决定写 ...

  6. JSON对象、JSON字符串的相互转换

    JSON对象.JSON字符串的相互转换 json的格式: 第一种方式: 单一的json字符串,转换成json对象时,需要 eval('(' + json + ')');这样的格式,中间需要加括号 va ...

  7. struts2 之 struts2类型转换

    1. 在struts2中,相比servlet来时,获取数据时,程序员没有进行手动的类型转换,类型转换工作都有struts2来完成处理,但愿对于自定义类型数据,struts2不会帮助我们完成类型转换工作 ...

  8. 数据库Schema两种含义~~

    1.数据库Schema有两种含义,一种是概念上的Schema,指的是一组DDL语句集,该语句集完整地描述了数据库的结构.还有一种是物理上的 Schema,指的是数据库中的一个名字空间,它包含一组表.视 ...

  9. 透视I/O多路复用

    透视I/O多路复用 我写的不是select这些函数的教学,需要了解的请自行Google或者去man,这些是帮助我理解函数的封装之下的道理. 需要回答的问题 I/O准备好了指什么?什么叫I/O已经可读/ ...

  10. 开发Angular库的简单指导(译)

    1. 最近工作上用到Angular,需要查阅一些英文资料,虽然英文非常烂,但是种种原因又不得不硬着头皮上,只是每次看英文都很费力,因此决定将一些比较重要的特别是需要反复阅读的资料翻译一下,以节约再次阅 ...