代理模式其实就是找替身,要去办一件事儿,自己不去,找人代替你去,这就是代理模式。在程序中就是,为对象提供一个替身,控制替身去访问目标对象,这样做的好处是,除了目标对象能提供的功能外,还可以让替身多做一些活,即可以扩展目标对象的功能。被代理的可以是远程对象、创建时开销很大的对象或者需要安全控制的对象。
代理模式主要分为以下三种:
静态代理
动态代理(又叫JDK代理、接口代理)
cglib代理(也属于动态代理的范畴)
「1、静态代理介绍:」
使用静态代理的时候,需要定义接口或者父类,被代理的对象和代理对象需要一起实现相同的接口或者继承相同的父类。
「2、应用实例:」
定义一个接口:
TeacherDao
定义被代理的对象:
TeacherDaoImpl
,需要实现
TeacherDao
定义代理对象:
TeacherDaoProxy
,也需要实现
TeacherDao
要调用
TeacherDaoImpl
方法时,需要先创建
TeacherDaoProxy
对象,然后创建
TeacherDaoImpl
对象,将
TeacherDaoImpl
对象交给
TeacherDaoProxy
对象,再调相关方法
TeacherDao.java:
<code>public interface TeacherDao {<br> void teach();<br>}<br></code>
TeacherDaoImpl.java:
<code>public class TeacherDaoImpl implements TeacherDao {<br> @Override<br> public void teach() {<br> System.out.println("今天又是没妹子的一天(ノへ ̄、)");<br> }<br>}<br></code>
TeacherDaoProxy.java:
<code>public class TeacherDaoProxy implements TeacherDao {<br> <br> private TeacherDao target; // 被代理的对象<br> <br> public TeacherDaoProxy(TeacherDao target){<br> this.target = target;<br> }<br> <br> @Override<br> public void teach() {<br> System.out.println("代理开始");<br> // 这里可以写一些额外的逻辑,以达到扩展被代理对象的目的,相当于spring的前置通知<br> target.teach();<br> // 这里也可以写一些额外的逻辑,以达到扩展被代理对象的目的,相当于spring的后置通知<br> System.out.println("代理结束");<br> }<br>}<br></code>
Client.java:调用代理对象
<code>public class Client {<br><br> public static void main(String[] args){<br> // 创建被代理的对象<br> TeacherDao target = new TeacherDaoImpl();<br> // 创建代理对象<br> TeacherDaoProxy proxy = new TeacherDaoProxy(target);<br> // 通过代理对象调用方法<br> proxy.teach();<br> }<br>}<br></code>
「3、静态代理的优缺点:」
优点:可以在不修改被代理对象的前提下扩展被代理的对象,做一些增强
缺点:需要实现相同的接口或者继承相同的父类,所以代理类会很多,而且如果接口或者父类有改动,代理对象和被代理对象都需要维护
「1、动态代理介绍:」
代理对象不要实现接口,但是被代理对象还是需要实现接口的。动态代理对象的生成,利用的是JDK的API,反射包下的Proxy类,动态地在内存中构建代理对象。
「2、java.lang.reflect.Proxy:」
这个类有一个newProxyInstance
方法,该方法接收三个参数,如下:
<code>static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)<br></code>
「3、应用实例:」
定义一个接口:TeacherDao
定义被代理的对象:TeacherDaoImpl,需要实现TeacherDao
定义一个代理工厂ProxyFactory,有一个getProxyInstance方法,需要传入被代理的对象,然后返回代理对象实例,通过代理对象调用被代理对象的方法
TeacherDao.java:
<code>public interface TeacherDao {<br> void teach();<br>}<br></code>
TeacherDaoImpl.java:
<code>public class TeacherDaoImpl implements TeacherDao {<br> @Override<br> public void teach() {<br> System.out.println("今天又是没妹子的一天(ノへ ̄、)");<br> }<br>}<br></code>
ProxyFactory.java
<code>public class ProxyFactory {<br><br> private Object target; // 被代理的对象<br><br> public ProxyFactory(Object target){<br> this.target = target;<br> }<br><br> // 给被代理的对象生成一个代理对象<br> public Object getProxyInstance(){<br> // 参数1:指定被代理对象的类加载器<br> // 参数2:被代理对象实现的接口类型<br> // 参数3:事件处理,执行被代理对象的方法<br> return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {<br> @Override<br> public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {<br> System.out.println("JDK代理开始");<br> // 调用方法,args的方法的参数<br> Object returnValue = method.invoke(target, args);<br> System.out.println("JDK代理结束");<br> // 将执行结果return<br> return returnValue;<br> }<br> });<br> }<br>}<br></code>
Client.java:通过代理调用方法
<code>public class Client {<br><br> public static void main(String[] args){<br> // 创建被代理的对象<br> TeacherDao target = new TeacherDaoImpl();<br> // 创建代理对象<br> TeacherDao proxy = (TeacherDao) new ProxyFactory(target).getProxyInstance();<br> // 通过代理对象调用被代理对象的方法<br> proxy.teach();<br> }<br>}</code>
「1、cglib代理介绍:」
静态代理和动态代理,被代理的对象,都需要实现接口,如果一个类没实现任何接口的,那就要用cglib代理了。cglib代理也叫子类代理,它会在内存中构建一个子类对象,从而实现对被代理对象的扩展。cglib代理底层是通过一个叫ASM的字节码处理框架来转换字节码并生成新的类从而实现代理的。被代理的类不能为final,否则会报错。被代理对象的方法如果是final/static,就不会被拦截,即不会执行被代理对象额外的业务方法。
「2、应用实例:」
首先要添加cglib相关依赖:
<code><dependency><br> <groupId>cglib</groupId><br> <artifactId>cglib</artifactId><br> <version>3.3.0</version><br></dependency><br></code>
TeacherDaoImpl.java:
<code>public class TeacherDaoImpl implements TeacherDao {<br> @Override<br> public void teach() {<br> System.out.println("今天又是没妹子的一天(ノへ ̄、)");<br> }<br>}<br></code>
CglibProxyFactory.java:
<code>// 需要实现MethodInterceptor并重写其方法<br>public class CglibProxyFactory implements MethodInterceptor {<br><br> private Object target;<br><br> public CglibProxyFactory(Object target){<br> this.target = target;<br> }<br><br> /**<br> * 返回target的代理对象<br> * @return<br> */<br> public Object getProxyInstance(){<br> // 1. 创建工具类<br> Enhancer enhancer = new Enhancer();<br> // 2. 设置父类<br> enhancer.setSuperclass(target.getClass());<br> // 3. 设置回调函数<br> enhancer.setCallback(this);<br> // 4. 创建子类对象,即代理对象<br> return enhancer.create();<br> }<br> @Override<br> public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {<br> System.out.println("CGLIB代理开始");<br> Object returnValue = method.invoke(target, args);<br> System.out.println("CGLIB代理结束");<br> return returnValue;<br> }<br>}<br></code>
Client.java:通过代理调用方法
<code>public class Client {<br><br> public static void main(String[] args){<br> // 创建被代理的对象<br> TeacherDaoImpl target = new TeacherDaoImpl();<br> // 获取代理对象,并将被代理对象传给代理对象<br> TeacherDaoImpl proxy = (TeacherDaoImpl) new CglibProxyFactory(target).getProxyInstance();<br> // 执行方法,触发intecept方法,从而实现执行被代理对象的方法<br> proxy.teach();<br> }<br>}<br></code>
以上是java代理模式怎么应用的详细内容。更多信息请关注PHP中文网其他相关文章!