代理相关总结

来源:互联网 发布:用python的turtle画图 编辑:程序博客网 时间:2024/05/22 15:50


主要内容:

1. 静态代理

2. AOP 和动态代理

3. 线程池

代理理解:

代理模式相关三个类:接口,委托类,代理类。
接口:是委托类和代理类共同方法的抽象。
委托类:就是客户们各种各样的方法需求。
代理类:不管什么样的方法,都能调用运行,并加上自己的一些系统功能处理。

而对应java语言实现的类包:
接口:java.lang.reflect.InvocationHandler

代理类:java.lang.reflect.Proxy

委托类:就是用户自定义但需实现接口的类

代理架构如 图:


图中的客户端是导火索,触发代理架构的运行。

静态代理示例:

接口:

package cn.itheima.day3;//接口interface Function {void function();}
委托类:

package cn.itheima.day3;//委托类public class MyTarget implements Function{@Overridepublic void function(){System.out.println("我需要代理");}}
代理类和客户端调用程序 :
package cn.itheima.day3;//代理类public class MyProxy implements Function{@Overridepublic void function(){System.out.println("我提供代理");//调用委托类的程序func.function();System.out.println("代理完毕");}private Function func;MyProxy(Function func){this.func = func;}//客户端调用程序public static void main(String[] args) throws Exception{// TODO Auto-generated method stubMyProxy mp = new MyProxy(new MyTarget());mp.function();}}

AOP:(Aspect Oriented Program)

系统中存在交叉业务,一个交叉业务要切入到系统中的一个方面。交叉业务的编程问题称为面向方面的编程。
而使用代理技术正好可以解决这种问题,代理是实现AOP功能的核心和关键技术。
重要原则:不要把供货商暴露给你的客户,就是不要让客户端知道委托类的底细,只用其功能。

动态代理:

要为系统中的各种接口的类增加代理功能,那是一件麻烦且痛苦的事情。动态代理可以一劳永逸解决这个麻烦。
JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。
CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。

代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:
    1.在调用目标方法之前
    2.在调用目标方法之后
    3.在调用目标方法前后
    4.在处理目标方法异常的catch块中

上述静态代理转成动态代理:
代码示例:(JDK动态代理)
package cn.itheima.day3.JDK;interface Function{void function();}
package cn.itheima.day3.JDK;public class MyTarget implements Function{@Overridepublic void function() {System.out.println("我要JDK动态代理");}}
package cn.itheima.day3.JDK;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class MyProxy implements InvocationHandler{ Object target;    public Object getProxy(final Object target)    {    this.target = target;    return Proxy.newProxyInstance(target.getClass().getClassLoader(),     target.getClass().getInterfaces(),    new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {Object retVal = null;System.out.println("JDK动态代理开始");retVal = method.invoke(target, args);System.out.println("JDK动态代理结束");return retVal;}});    }@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable{/*Object retVal = null;System.out.println("JDK动态代理开始");retVal = method.invoke(target, args);System.out.println("JDK动态代理结束");return retVal;*/return null;}//直接用匿名内部类}
package cn.itheima.day3.JDK;public class MyProxyTest {/** * @param args */public static void main(String[] args)throws Exception {// TODO Auto-generated method stubMyProxy mpro = new MyProxy();//这里得用接口强转型,用子类转型会异常Function mtar = (Function)mpro.getProxy(new MyTarget());mtar.function();}}

线程池:

一些线程的集合就是线程池。
当服务器接受到一个客户请求后,就从线程池中取出一个空闲的线程为之服务,服务完后不关闭该线程,而是将该线程还回到线程池中。
在线程池的编程模式下,任务是提交给整个线程池,而不是直接交给某个线程,线程池在拿到任务后,它就在内部找有无空闲的线程,再把任务交给内部某个空闲的线程,这就是封装。
记住:任务是提交给整个线程池,一个线程同时只能执行一个任务,但可以同时向一个线程池提交多个任务。
一个线程池包括四个基本组成部分:
1、线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
2、工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
4、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。

与线程池相关的类包:
java.util.concurrent
ExecutorService:真正的线程池接口。
ScheduledExecutorService:能和Timer/TimerTask类似,解决那些需要任务重复执行的问题。
ThreadPoolExecutor :ExecutorService的默认实现。
ScheduledThreadPoolExecutor:继承ThreadPoolExecutor的ScheduledExecutorService接口实现,周期性任务调度的类实现。

创建线程有两种方式:继承Thread或实现Runnable。
Thread实现了Runnable接口,提供了一个空的run()方法,所以不论是继承Thread还是实现Runnable,都要有自己的run()方法。
一个线程创建后就存在,调用start()方法就开始运行(执行run()方法),调用wait进入等待或调用sleep进入休眠期,顺利运行完毕或休眠被中断或运行过程中出现异常而退出。

关闭线程池
shutdown:
shutdownNow:

用线程池启动定时器:
调用ScheduledExecutorService的schedule方法,返回的ScheduleFuture对象可以取消任务。
支持间隔重复任务的定时方式,不直接支持绝对定时方式,需要转换成相对时间方式。

代码示例:
package cn.itheima.day3;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class ThreadPoolTest {public static void main(String[] args) {//ExecutorService service = Executors.newFixedThreadPool(3);ExecutorService service = Executors.newCachedThreadPool();for(int i=1;i<=10;i++){final int sequence = i;//仔细品味runnable对象放到循环里面和外面的区别,为了让每个对象有自己独立的编号service.execute(new Runnable(){public void run() {try{Thread.sleep(200);}catch(Exception e){}for(int j=1;j<=5;j++){System.out.println(Thread.currentThread().getName() + "is serving " + sequence + " task:" + "loop of " + j);}}});}/*用下面这句代码来说明上面的代码是在提交任务,并且所有的任务都已经提交了,但任务是什么时候执行的,则是由线程池调度的!*/System.out.println("all task have committed!");//注意与service.shutdownNow()的区别。service.shutdown();ScheduledExecutorService scheduledService = Executors.newScheduledThreadPool(1);scheduledService.scheduleAtFixedRate(new Runnable(){public void run() {System.out.println("bomb!!!");}}, 5, 1,TimeUnit.SECONDS);}}


0 0