A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

同学们,今天讲了一个很重要的概念就是动态代理,网上商城项目主要学习设计了一个通用Servlet类。

今日需要掌握的有:
  • 今天讲的是JDK动态代理,注意掌握它的特点,后面框架阶段我们还将学习另外一种CGLib动态代理
  • 通用Servlet类即BaseServlet,也可以当作是一个工具类,要理解其中的调用关系

请同学们按照如上要求,总结今日所学。


19 个回复

倒序浏览
许剑鸿      webDay25


Proxy 动态代理(今日重点): 进行类的增强

增强类使用的方法:
Proxy.newProxyInstance(类加载器,实现的接口列表,InvocationHandler实现类)
增强的内容就是InvocationHandler实现类中invoke方法中的内容
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。


【Spring的AOP】AOP的底层使用的就是代理机制
AOP:面向切面编程.新的思想,用来解决OOP中遇到的一些问题!!!管理事物


类加载器:将class文件加载到JVM中执行这个文件.

JDK类加载器的分类:
引导类加载器:JAVA_HOME/jre/lib/rt.jar
扩展类加载器:JAVA_HOME/jre/lib/ext/*.jar
应用类加载器:加载类路径下的所有的class.

委托机制:保证类只会加载一次而且不会重复加载

class A {
         String s;
}
    由应用类加载器得到A.class String,class,委托给扩展类加载器,扩展类加载器又委托给引导类加载器.
引导类加载器加载String.class.将其他的类的class向下给扩展类加载器.扩展类加载器没有找到.向下
给应用类加载器,将A.class 加载.
回复 使用道具 举报
谢洪彬:
动态代理:
用于增强类的方法:
继承:        能够控制这个类的构造时使用这个方式
装饰者模式:        增强和被增强的类都要实现同一个接口,增强的类中获取被增类的引用
动态代理:        增强的类需要实现一个接口
主要方法:        Proxy.newProxyInstance(loader, interfaces, h)
                 *         参数一:        被增强类的加载器       
Class对象.getClassLoader()
                 *         参数二:        被增强类所实现的所有接口
Class对象.getInterfaces()
                 *         参数三:        具体加强的实现
new InvocationHandler()
BaseServlet:
今天我们使用BaseServlet去就解决了用Servlet创建过多和代码复用性强的问题:
思路分析:
1.定义BaseServlet去继承HttpServlet,并重写里面的Servlet方法.
2.在Servlet中先获取表单提交的method属性值:也就是方法名;
3.同时this.getClass()获取继承BaseServlet类的Class对象(哪个Servlet类调用及获取该类的Class对象);
4.获取Class对象就可以获取类中指定的方法并调用;
5.在编写Servlet类中就可以去实现我们自己编写的BaseServlet类,并传递HttpServletRequest和HttpServletResponse对象;
6.在jsp中需要提交的有方法名
回复 使用道具 举报
吴鹏

总结

动态代理...
感觉就是个中介(不谈及钱,只谈服务,房东不可能为了租/卖房子陪你一整天)
JDK中的代理:Proxy类(反射包里)
Proxy.newProxyInstance(ClassLoader cl,Class[] interface,InvocationHandler ih);

类加载器

被增强的类的实例化对象所实现的所有接口
以上两个参数就可以知道想要增强的类中的所有实现的方法(实现了接口的方法)


InvocationHandler
是一个接口,写一个类实现这个接口,这个接口只有一个invoke方法需要实现,
在invoke里面要写上要增强的对象的方法,这样以后调用增强偶的对象的时候,
不管调用这个对象的什么方法,都是只执行增强后的方法,针对这点,下面还有解决的方法

通过判断方法名的方式,来判断传进来的方法是否是我们要增强的方法,
通过使用invoke方法里面的三个参数
proxy    产生的代理对象
method    当前正在调用的目标类的方法
params    正在执行的方法中的参数

if("要增强的方法名".equasl(method.getName()) {
增强的内容
}else {
不做改变
}
return method.invoke();//这个是通过反射,返回method调用方法后(不管有没有增强)的结果;

-------------------------------------------
在过滤器中使用动态代理完成字符集转换的案例

------------------------------------------
代理的企业应用:
Spring的AOP
底层使用的就是代理机制
面向切面编程,用来解决OOP中遇到的一些问题

--------------------------------------------

类加载器
将class文件加载到jvm中执行这个文件;
java中将类的加载器分成3类

引导类加载器  加载的是jre/lib/rt.jar
上层
扩展类加载器  加载的是jre/lib/ext/下所有的jar
中层
应用类加载器  加载的是自定义的Java文件编译后的类文件
下层
三层不是继承的,是根据负责加载的类的类型来分

这些类加载器是如何保证类只会家在一次,而且不会重复加载
类加载器的全盘委托机制:
从下层开始往上层委托,到最上层开始,加载负责自己应该加载的类,剩下的就再次委托到下层,每层只加载
自己负责的那部分类,这样就保证类只加载一次;

EE中的类加载器又扩展了两个;

-----------------------------------------
关于BaseServlet的作用原理:

BaseServlet中定义了service方法,当发送请求时会从service中执行,,当发送请求到一个继承了BaseServlet的子类Servlet时,因为
子类继承了BaseServlet也就继承了它的所有的方法,因此,请求发送过来时,,此时的service已经是被子类继承后的service,
BaseServlet相当于一个工具类,被子类所继承使用,但是代码当中的this指的是子类对象;


回复 使用道具 举报
张裕
动态代理:增强方法的其中一种方式 灵活性较大
JDK中的动态代理类: Proxy

创建动态代理对象需要的参数
        1 类加载器
        2 类的接口数组
        3 进行操作的对象(需要实现invocationHandler接口)

增强的方法必须为接口中的方法 实现类中自定义的方法不能增强

动态代理对象没调用一次方法 默认执行invoke方法
invoke中的参数
        proxy: 代理对象
        method: 当前正在调用的目标类的方法
        params: 正在执行的方法中的参数

编码过滤器的编写
        1 将doFilter中的request对象向下转型为HttpServletRequest
        2 调用Proxy.newProxyInstance 传入request的类加载器 接口数组 invocation匿名对象 获得动态代理对象 强转为HttpServletRequest
        3 在匿名对象中判断方法名是否为getParameter 判断提交方式为get还是post 根据方式解决编码问题
        4 chain.doFilter放行 !!传入新的request对象

代理的企业应用
        AOP: 面向切割编程 将一个操作分为好几层 不修改源代码的情况下进行业务的修改操作
类加载器
        将class文件加载到JVM中执行这个文件

种类:
        引导类加载器
                  ↑
        扩展类加载器
                  ↑
        应用类加载器

全盘委托机制
        由应用类加载器得到A.class String,class,
委托给扩展类加载器,扩展类加载器又委托给引导类加载器.
引导类加载器加载String.class.将其他的类的class向下给扩展类加载器.
扩展类加载器没有找到.向下给应用类加载器,将A.class 加载.

                商城项目
编写通用的Servlet
        1 创建一个class类 继承HttpServlet类
        2 重写service方法
        3 获取提交的方法名称
        4 获取调用该方法的类字节码对象
        5 通过字节码对象查询指定的方法 获取方法对象
        6 invoke执行方法 接收返回值        (方法中的返回值写为path)
        7 通过返回的路径转发页面
       
回复 使用道具 举报
陈强
动态代理&商城搭建的一天;
动态代理,今天主要学习它使用在增强方法上,
----Proxy . newProxyInstance() , 三个参数:
                ---类加载器 : classLoader
                ---接口数组 : 被增强对象所实现的所有接口
                ---处理类 : InvocationHandler ( 是一个接口 )---核心部分,就是方法是如何加强的
然后就是方法的执行:
---invoke() , 三个参数:
                ---proxy : 产生的代理对象
                ---method : 当前正在调用的目标类的方法
                ---params : 正在执行的方法中的参数
这里需要注意!!!要增强的方法必须是接口中方法,实现类中自有的方法没办法增强!!!
类的加载器:就是将class文件加载到虚拟机中(JVM);
---分为以下三种类加载器:
        ---引导类加载器 : JAVA_HOME/jre/lib/rt.jar
        ---扩展类加载器 : JAVA_HOME/jre/lib/ext/*.jar
        ---应用类加载器 :加载类路径下的所有class
---全盘委托机制---保证只会被加载一次不会重复加载!
然后就是对商城的一个简单的搭建:
主要的就是使用一个BaseServlet作为一个通用的servlet,这个servlet不用去配置,所以直接创建一个class去继承HttpServlet,然后重写service就可以了
回复 使用道具 举报
许煜 每日总结
Web增强day2
动态代理增强
  前提 被增强的类实现接口即可 动态代理比起装饰者模式的优势在于动态代理更加直接以及灵活,装饰者模式增强类需要被增强类实现同一个接口,在增强类中获得被增强类的引用.以及若是没有提供准备好的模板类(包装类),装饰者模式需要实现接口全部方法,而动态代理可以利用反射直接加强需要增强的方法.
动态代理实现细节
   类加载器 class.getclassloader( ).
   所有接口 class.getinterfs(),
   代理类 InvocationHandler( )用于实现增强内容
Proxy.newProxyInstance(classloader, interfaces,new InvocationHandler( ){ });
InvocationHandler是一个接口 可通过创建匿名内部类 和创建InvocationHandler实现类来充当代理类
重写InvocationHandler 的invoke的方法来增强方法 通过方法名匹配调用指定代码块 若是不需要增强的方法 则直接返回原方法调用
动态代理处理编码乱码
        // 动态代理处理乱码
        public void doFilter(ServletRequest request, ServletResponse response,
                        FilterChain chain) throws IOException, ServletException {
                // 这里为什么要求用final?//匿名内部类调用的参数必须为final修饰 ? 规定
                final HttpServletRequest req = (HttpServletRequest) request;
                // 类加载器
                ClassLoader cl =req.getClass().getClassLoader();
                // 接口集合
                Class<?>[] interfaces = req.getClass().getInterfaces();
                // 增强req
                HttpServletRequest myReq = (HttpServletRequest) Proxy.newProxyInstance(cl, interfaces, new InvocationHandler() {
                                        @Override
                                        public Object invoke(Object proxy, Method method,
                                                        Object[] args) throws Throwable {
                                                if ("getParameter".equals(method.getName())) {
                                                        String type = req.getMethod();
                                                        if ("get".equalsIgnoreCase(type)) {
                                                                String value = (String) method
                                                                                .invoke(req, args);
                                                                value = new String(
                                                                                value.getBytes("ISO-8859-1"), "UTF-8");
                                                                return value;
                                                        } else if ("post".equalsIgnoreCase(type)) {
                                                                req.setCharacterEncoding("UTF-8");
                                                        }
                                                }
                                                return method.invoke(req, args);
                                        }
                                });
                chain.doFilter(myReq, response);
        }
BaseServlet存在的意义 避免一个请求就创建一个Servlet,提供公共Servlet以提高代码的复用性.
原理:需要传递的参数为调用的方法名 利用反射通过方法名调用方法,baseServlet继承httpServlet后,其余sevlet只需继承baseServle即可
难以理解的点:this.getclass(),this永远表示的是当前类的对象,继承类继承baseServlet后代码执行到this.getclass()获得到的class对象就是自己的class(),这个时候super.class代表的才是其父类的class对象
继承baseServlet()的类不用再重写service方法且将方法返回对象设为path更方便请求后进行页面的跳转等操作
代码如下
        public void service(HttpServletRequest request, HttpServletResponse response)
                        throws ServletException, IOException {
                // 通过连接将方法名传过来
                String methodName = request.getParameter("method");
                // 反射 通过方法名调用
                Class clazz = this.getClass();// 继承类调用时获得的是自己本身的class对象
                try {
                        Method method = clazz.getMethod(methodName,HttpServletRequest.class, HttpServletResponse.class);
                        // 调用方法
                        String path = (String) method.invoke(this, request, response);
                        // 将register login等方法返回值设为string路径更方便坐页面跳转等后续处理
                        if (path != null) {
                                request.getRequestDispatcher(path).forward(request, response);
                        }
                } catch (Exception e) {               
        e.printStackTrace();
                }
        }
回复 使用道具 举报
光宇 中级黑马 2018-6-19 21:31:52
8#
侯玉林

1.什么是动态代理:主要用于增强类的方法中
        方法增强的三种办法之一:
        request中的方法的增强:
        1.继承:能够控制这个类的构造.
        2.装饰者:增强的类和被增强的类实现相同的接口,增强的类中获得到被增强的类的引用.
        * 接口中方法过多,只增强其中的某个方法.其他的方法也需要重写.
        3.动态代理        :被增强的类实现了接口.

2.代理的概述:
        使用动态代理:Proxy.newProxyInstance();

3.代理的条件:
        该增强的类至少实现了,一个或多个的接口
        增强的方法必须是接口中的方法,实现类中的自己特有的方法无法增强.

4.如何实现代理:
        实现流程:
       
                1.通过interfaces接口的数组,虚拟机知道了要增强类的所有有实现接口,
                进而知道该增强类所有接口的实现方法.
               
                2.通过该接口数组,虚拟机会为该增强类创建一个实现了同样接口数组的
                类,假设该类为增强类2.
               
                3.增强类2中的所有的接口实现后的方法都默认调用invocationHandler ih
                对象中的invoke方法.
回复 使用道具 举报
万冕

动态代理

被增强的类.实现了接口
首先先自己写一个接口,然后再创建一个类去实现这个接口,然后再调用

重要!!!
Proxy.newProxyInstance(ClassLoader cl,Class[] interfaces,InvocationHandler ih)

第一个参数,类加载器,就是本类.getclass.getClassLoaer
第二个参数 是类实现的接口的数组:类名.getclass.getinterfaces
第三个参数 是处理类

创建一个类去实现InvocationHandler
private Waiter waiter;

        public MyInvocationHandler(Waiter waiter){
                this.waiter = waiter;
        }

        !!!!!!!!!!调用代理对象的任何方法的时候,InvocationHandler中的invoke都会执行.

类加载器就是将class文件加载到JVM中

加载器分三类:引导类,扩展类,应用类

类加载器的全盘委托机制
class A {
      String s;

}

由应用类得到A.class String.class,委托给扩展类,拓展类又委托给引导类,由引导类加载String.class ,将其他的类给扩展类加载
如果扩展类没有找到,就交给应用类将A.class加载
回复 使用道具 举报
常小天
今天的学习内容有两部分。第一部分是基础加强的内容,学习的是动态代理。动态代理可以增强一个方法。它的要求要比装饰者模式更低,它只需要被增强的类实现了接口就可以。我们使用Proxy对象来实现动态代理,用到的静态方法是Proxy.newProxyInstance(ClassLoader cl,Class[] interfaces,InvocationHandler ih),返回的是一个增强过的对象。这里的三个参数分别是类加载器(ClassLoader),被增强类所实现的所有接口(Class[] interfaces),以及对方法进行处理的对象(InvocationHandler)。类加载器可通过任意类的class对象调用getClassLoader()方法获得。被增强类所实现的接口数组通过被增强类的class对象调用getInterfaces()方法获得。难度最大的是第三个参数。第三个参数是一个对象,我们可以通过匿名内部类或者单独编写一个类实现InvocationHandler接口来获得这个对象。静态方法返回的增强过的对象包含了被增强类所实现的所有接口中的方法。使用这个增强过的对象调用接口中的方法时,都会转而调用InvocationHandler对象内重写的invoke(Object proxy, Method method, Object[] args)方法。在invoke方法判断调用的是哪个方法,如果是需要增强的方法,就改写方法体,如果不是就调用method.invoke(Object, Object[])执行方法。
今天学习的第二部分是商城环境搭建。这是商城案例的准备工作,主要有4个内容要做。首先是引入jar包,mysql驱动包1个,C3P0包1个,dbutils包1个,beanutils包2个,jstl包2个,mail包1个,fileupload的包2个。接下来创建包结构,第三步引入工具类和C3P0的配置文件,最后一步是编写通用的servlet。这个servlet继承了HTTPServlet并重写了service方法,它的作用是抽取servlet中的公共部分,简化代码的编写。首先我们不用每一种请求响应都写一个servlet,而是分模块,将同一模块的请求响应编写到一起,例如用户方面的操作写入一个用户模块、商品方面的操作写入一个商品模块等等。其次我们不用再每一个模块内都对传入的操作信息进行判断进而调用不同的方法,而是让其他的servlet继承这个通用的servlet,在通用servlet中判断传入的操作需要调用哪个方法,利用反射获得子类的方法并执行。当然在这个通用的servlet中只是写好了执行方法的流程,而实际的方法执行仍然是在子类中进行的。这是因为子类继承了通用的servlet,也就继承了他的service方法。同样因为这个原因,我们可以在通用servlet中使用this关键字获取子类的class对象。此外需要注意两个点,一是jsp中需要传递一个信息来标识请求的操作类型,二是模块servlet中编写的各种实现操作的方法都需要两个参数,分别是HttpServletRequest req, HttpServletResponse resp。
回复 使用道具 举报
郑雪平

今天学习了使用动态代理来实现编码过滤器的编写和网上商城实战案例的编写。我们之前学习了两种提交方式,分别是GET和POST。那么不管是使用哪种方式在Servlet中都只需要调用request.getParameter方法,中午乱码就可以处理好,我们要对request中的方法进行增强,增强的方法有:1.继承;2.装饰者;3.动态代理。我们着重学习动态代理,动态代理是被增强的类实现了接口,JAVA中的动态代理是proxy对象。这当中还学习了类加载器,作用是将CLASS文件加载到虚拟机中执行这个文件。类加载器被分成了三类:1.引用类加载器;2.扩展类加载器;3.应用类加载器;同时依托类加载器的全盘委托机制,这样来保证类只会被加载一次而不会被重复加载。
  第二部分是网上商城实战案例代码实现,前期需先进行开发环境的搭建,具体实施步骤:1.引入相关开发JAR包,分别是:Mysql, Dbutils,Beanutils,Jstl,c3p0,Mail,Fileupload等JAR包;2.创建包结构(Servlet,dao,domain,service,utils,filter,listener);3.引入相关的工具类和配置文件;4.编写通用的Servlet(Baseservlet).
回复 使用道具 举报
汪志阳:
在request中方法的增强有三种方式:1.继承:需要控制方法所在类的构造;2.装饰柱模式:增强的类和被增强的类需要实现相同的接口,增强的类中获得被增强类的引用,缺点就是如果只要增强
其中的某个方法,其他方法也需要重写,为此我们引入了更加灵活的动态代理.动态代理抓哟是proxy对象该方法的使用
Proxy.newProxyInstance(ClassLoader cl,Class[] interfaces,InvocationHandler ih)
ClassLoader:类的加载器,通过调用类的getClassLoader进行获取;
Class[] interfaces:类中实现的接口的数组,通过类的getInterfaces方法获取;
最后的InvocationHandler,需要创建匿名内部类public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {}我们增强的方法就是通过调用该匿名内部类实现的
        @Override
                                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                                // 判断执行的方法是否是getParameter,需要增强这个方法
                                                if("getParameter".equals(method.getName())){                                                       
                                                        // 判断请求方式是GET还是POST:
                                                        String type = req.getMethod();
                                                        if("get".equalsIgnoreCase(type)){
                                                                String value = (String) method.invoke(req, args);
                                                                value = new String(value.getBytes("ISO-8859-1"),"UTF-8");
                                                                return value;
                                                        }else if("post".equalsIgnoreCase(type)){
                                                                req.setCharacterEncoding("UTF-8");
                                                        }
                                                }
                                                return method.invoke(req, args);
                                        }
                                });
               
                chain.doFilter(myReq, response);
        }
这个动态代理,引入了新的思想面向切面,就是程序由jsp到servlet再到dao执行的顺序执行,我们在中间某一位置需要插入功能,切入的插入代码的思想.
编写一个BaseServlet:通用的servlet,主要是为了解决传统方试servlet创建过多带来的问题
@Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                req.setCharacterEncoding("utf-8");
                resp.setContentType("text/html;charset=utf-8");
                // 接收参数:http://localhost:8080/store_v2.0/UserSErvlet?method=regist
                String methodName = req.getParameter("method");
                if (methodName == null || "".equals(methodName)) {
                        resp.getWriter().println("获取的参数为null!!!");
                        return;
                }
                try {
                        // Class<? extends String> class2 = methodName.getClass();regist方法:
                        // public String regist(HttpServletRequest req,HttpServletResponse
                        // resp){
                        // return “/login.jsp”;}
                        // 继承的是String,获取当前子类对象
                        Class<? extends BaseServlet> clazz = this.getClass();
                        // 获取方法
                        Method method = clazz.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
                        // 使用方法invoke(调用方法的对象,方法参数),返回路径"login.jsp"
                        String path = (String) method.invoke(this, req, resp);
                        if (path != null) {
                                req.getRequestDispatcher(path).forward(req, resp);
                        }
                } catch (Exception e) {
                        e.printStackTrace();
                }
这个通用的servlet主要运用反射机制,比较难理解的是代码中的两个this,这个servlet看成一个工具类,其他userServlet继承该类,this代表的就是继承该类的那个使用类,继承的类返回一个jsp的路径.       
回复 使用道具 举报
陈叶隆
        JDK中动态代理        :Proxy对象.
Proxy.newProxyInstance(ClassLoader cl,Class[] interfaces,InvocationHandler ih);
案例: 使用动态代理完成字符集编码过滤器的编写
final HttpServletRequest req=(HttpServletRequest) request;
                ClassLoader loader = req.getClass().getClassLoader();
                Class[] interfaces = req.getClass().getInterfaces();
        HttpServletRequest myReq = (HttpServletRequest) Proxy.newProxyInstance(loader, interfaces, new InvocationHandler() {
                                        @Override
public Object invoke(Object proxy, Method method, Object[] args)                                        throws Throwable {
                                // 判断执行的方法是否是getParameter
                        if("getParameter".equals(method.getName())){
                                String type = req.getMethod();
                                if("post".equalsIgnoreCase(type)){
                                        req.setCharacterEncoding("utf-8");
                                }
                                else if("get".equalsIgnoreCase(type)){
                                        String value = (String) method.invoke(req, args);
                                        String val = new String(value.getBytes("ISO-8859-1"),"UTF-8");
                                        return val;
                                }
                        }
                                return method.invoke(req, args);
                        }
                });
                chain.doFilter(myReq, response);
回复 使用道具 举报
郭明杰
动态代理:
用于增强类中的 方法: Proxy.newProxyInstance(加载器, 被增强类的所有接口,  Proxy.newProxyInstance(loader, interfaces, )

AOP:面向切面编程用来解决OOP中遇到的一些问题,底层用的就是代理

类的加载器:将class文件加载到JVM中执行这个文件
java中类加载器有三种 :引导类加载器:扩展类加载器:应用类加载器:
回复 使用道具 举报
郑志祥
早上学习2个知识点

知识点一
继承;必须要知道类名 (也是一个缺点)
传接口是为了 知道里面有多少方法

1.先创建一个接口(里面有两个方法1,服务 2.sayhello)
2.编写一个类去实现这个解口,重写里面的方法(添加方法执行的内容)
3.编写一个测试类(记得写注解,)
4,核心 动态代理.静态方法(类的加载器,接口数组,匿名对象(myinvocationHandler)传入参数)
5.创建一个Myinvocation实现invocation(重写里面的invoke的执行的方法)为上面的参数,编写一个有参构造
6.判断是否是我们要增强的方法。

(类的加载器,接口数组(可以得到原来的方法),创建MyInvocationHandler匿名对象(参数)-传入参数可以得到方法里面的的具体操作)
动态代理就是通过  Waiter waiter2 = (Waiter)Proxy.newProxyInstance(classLoader, interfaces, new MyInvocationHandler(waiter));
这个的一个方法,在创建一个MyInvocationHandler这样一个类来实现InvocationHandler。注意(如果 new MyInvocationHandler(waiter)有传参,可以实现构造函数)里面有一个invoke的方法,这是一个反射,无论调用什么方法都会执行invoke这个方法,这也是动态代理的核心


知识点二

1、创建一个jsp 上面体现get与post的提交方式(form表单)
2、创建一个servlet  (1.在对应的提交方法中接收相对应的参数,并打印内容是否为乱码)
3、编辑一个类实现Filer过滤器,利用动态代理,进行增强getPramert  让结果不为乱码




通过动态代理的方法来对request来进行加强(让request可以自动识别乱码) 注意request需要用finaly来修饰,因为finaly修饰的方法不会被修改

2.和上面的区别:注意我们不知道是哪一个类,所以不能进行传参,也无法进行无参构造




下午知识点三(编写BaseServlet的基础工具类)
1.编写一个类继承HttpServlert  (调用里面的Service这个方法)
2.解决乱码问题,接收参数
3.获得子类对象(判断获得方法是否为null或者是空字符串)
4.获得子类方法(方法,res对象,rep对象)
4.使方法执行(获得路径path) 方法。invoke(this,res,rep)
5.如果path不等与null就进行页面跳转
回复 使用道具 举报
郑阳阳
动态代理:
方法的增强有三种方式:继承,装饰者模式和动态代理.
动态代理是最灵活的,只需要被增强的类实现接口.
JDK中的动态代理使用的是Proxy对象.

BaseServlet其中的调用关系:
主体类继承BaseServlet,主体类中编写各种注册,登录之类的方法,通过提交参数的时候
传入method的值来判断执行哪种方法
回复 使用道具 举报
5119 中级黑马 2018-6-20 21:07:58
17#
游荣辉
总结
        今天学习了动态代理:
        JDK中的动态代理  :porxy对象
        这个对象基本都是调用newPorxyInstance(ClassLoader cl,Class[] interfaces,InvocationHandler ih);这个方法
                第一个参数是:加载器         第二个参数:这个类实现了多少类      第三个参数:传一个类,类中写着如何增强
        反射:字节码对象.getMethod()是获得方法
             字节码对象.getinvoke()是调用方法
        【Spring的AOP】AOP的底层使用的就是代理机制
                AOP:面向切面编程.新的思想,用来解决OOP中遇到的一些问题!!!管理事物
回复 使用道具 举报
刘文峰:
动态代理可以用来增强方法,使方法的功能变得更强大.使用条件也很简单,只要被增强类实现了接口就可以了.proxy是jdk中的动态代理类,里面有个静态方法就可对方法进行增强:
proxy.newProxyInstance(ClassLoader cl,Class[] interfaces,InvocationHandler ih);
ClassLoader :被增强对象的加载器,
Class[] interfaces :被增强类实现的所有接口
InvocationHandler ih :这是一个接口,需要传入这个接口的实现类(可以用匿名内部类),这个接口里面只有invoke(Object proxy, Method method, Object[] args)一个方法,每次调用被增强类实现的接口里的方法时都相当于调用了这个方法,因此,这个方法里就可以实现对方法的增强.通过method.getName()获得正在调用的方法的方法名判断是否是我们要增强的方法,如果是,就可以对这个方法进行增强.

BaseServlet:
在之前的学习中,项目的每一个功能都要创建一个servlet实现,当功能较多时就需要创建大量的servlet.我们可以创建一个servlet,例如BaseServlet,BaseServlet继承了HttpServlet,其他的servlet继承BaseServlet,不需要重写doget等方法,只要写具体操作的方法就行了.在BaseServlet的service方法里通过反射来获得其他servlet的方法并执行.比较难以理解的应该是字节码对象的获取方式:  Class clazz = this.getClass();  访问BaseServlet的servlet可能不止一个,所以用this可以解决如何获取不同servlet的字节码对象问题.比如A,B两个servlet都继承了BaseServlet,用户通过Aservlet的访问路径来到BaseServlet,此时this就代表Aservlet.同理,BServlet也是一样的.
要注意的是,继承BaseServlet的子类里不能重写service方法,否则用户会直接访问子类的service方法,不会访问BaseServlet的service方法.
回复 使用道具 举报
李思贤:一:用户模块
1:编写通用Servlet
传统的方式会导致整个项目Servlet很多,现在让一个模块只用一个通用的Servlet

搭建开发环境:
步骤一:引入开发jar包:
1:mysql    1
2:c3p0     1
3:dbutils   1
4:beanutils  2
5:jstl      2
6:mail     1
7:fileupload 2



步骤二 :创建包结构
Domain  dao service  utils  web
Web下创建servlet listener  filter





步骤三:引入工具类和配置文件
JDBC    C3P0配置文件



步骤四:编写通用Servlet
在utils中写BaseServlet  不需要配置
继承HttpServlet 重写service方法
注意乱码  接收参数method
获得子类class对象 this.getClass();
获得子类中方法 getMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);
执行.

代码如下:public class BaseServlet extends HttpServlet{

        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp)
                        throws ServletException, IOException {
                req.setCharacterEncoding("UTF-8");
                resp.setContentType("text/html;charset=UTF-8");
                //接收参数
                String methodName = req.getParameter("method");
                if(methodName==null||"".equals(methodName)){
                        resp.getWriter().println("method为null");
                        return;
                }
                //获得子类Class对象
                Class clazz = this.getClass();
                //获得子类方法
                try {
                        Method method = clazz.getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);                       
                        String path = (String) method.invoke(this, req,resp);
                        if(path!=null){
                                req.getRequestDispatcher(path).forward(req, resp);
                        }
                } catch (Exception e) {
                        e.printStackTrace();
                }                
        }       
}
回复 使用道具 举报
动态代理
        概述
                适用场景——编译时无法确定需要实现哪个接口时才有必要使用
                使用原理
                        1.在程序处于运行状态时,动态创建一个新类(实现被增强类实现的所有接口),并获得该类的对象(即动态对象)
                        2.无论何时调用代理对象的方法,调用代理器的invoke方法都会被调用,并向其传递Method对象和原始的调用参数。
                使用原因
                        路由对远程服务器的方法调用
                        在程序运行期间,将用户接口事件与动作进行关联
                        为调试,跟踪方法调用
                代理的企业应用
                        Spring的AOP底层使用的就是代理机制(AOP面向切面编程)
        Proxy对象
                static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
          返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
                ClassLoader loader——类加载器
                        作为Java安全模型的一部分,对于系统类和从因特网下载的类,可以使用不同的类加载器
                        Class类
ClassLoader getClassLoader()
          返回该类的类加载器。
                Class<?>[] interfaces——被增强类的所有接口
                        Class类
Class<?>[] getInterfaces()
          确定此对象所表示的类或接口实现的接口。
                InvocationHandler h——处理类
                        InvocationHandler接口
Object invoke(Object proxy, Method method, Object[] args)
          在代理实例上处理方法调用并返回结果。
                        Method类
Object invoke(Object obj, Object... args)
          对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
        类加载器
                作用——将.class文件加载到JVM中,得到字节码文件
                分类
                        引导类加载器
                                JDK(JAVA_HOME/jre/lib/rt.jar)
                                JVM的一部分(JVM是用C语言编写的)
                        扩展类加载器
                                JDK(JAVA_HOME/jre/lib/exe/*.jar)
                        应用类加载器
                                类路径下的所有class(自定义)
                保证类只被加载一次不被重复加载
                        类加载器的全盘委托机制
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马