什么是代理模式?
1.1 代理模式就是给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。
通常来说,我们在一个业务实现类中,我们需要去做一件事情,但是这件事情,我们不能直接去做,这个时候,我们就会委托一个第三方来帮我 干这件事情。这种模式就叫做代理模式。
代理模式由代理者以及被代理者二者构成,我们的代理者会帮我去完成一部分事情,但是最终的执行动 作,还是由我们被代理者去完成。
1.2代理模式常用场景:
拦截器,日志监听,无侵入式功能增强,AOP实现
1.3 代理模式分为静态代理和动态代理
静态代理
目标类与代理类继承同一个类或者实现同一个接口,使用时通过代理调用目标类的方法。
静态代理实现方式
(1)被代理者是固定的,代理者持有被代理者的句柄(引用),帮被代理者去完成一些事情。
(2)静态代理通常可以用两种方式来实现。
第一种,直接持有被代理类(被代理者)的句柄,实现代理方法,增强逻辑 。
第二种,定义一个接口或者抽象类,共同继承类或者接口,实现被代理的方法,在逻辑增强后再交由被代理者执行。
第一种:
被代理类SuperStar.java
package staticproxy;
public class SuperStar
{
public void moveShow()
{
System.out.println("我在演戏.........");
}
}
代理类:SuperStarProxy.java
package staticproxy;
public class SuperStarProxy
{
private SuperStar superStar;
public SuperStarProxy(SuperStar superStar)
{
this.superStar = superStar;
}
public void moveShow()
{
System.out.println("导演XXX. ,给我们superStar排戏........");
System.out.println("导演:OK,让她来.......");
System.out.println("经理人:导演让你去试戏.......");
this.superStar.moveShow();
System.out.println("XXX,一炮而红.........");
}
}
测试类ProxyTest
import staticproxy.SuperStar;
import staticproxy.SuperStarProxy;
import java.lang.reflect.Proxy;
public class ProxyTest
{
public static void main(String[] args) {
//静态代理
SuperStarProxy superStarProxy = new SuperStarProxy(new SuperStar());
superStarProxy.moveShow();
}
}
第二种:
创建一个接口,代理类与被代理类都继承接口
接口:SuperStar0213
package staticproxy;
public interface SuperStar0213 {
public void moveShw();
}
被代理类:SuperStar
package staticproxy;
public class SuperStar implements SuperStar0213
{
public void moveShw() {
System.out.println("我在演戏.........");
}
}
代理类:SuperStarProxy
package staticproxy;
public class SuperStarProxy implements SuperStar0213
{
private SuperStar superStar;
public SuperStarProxy(SuperStar superStar)
{
this.superStar = superStar;
}
public void moveShw() {
System.out.println("导演XXX. ,给我们superStar排戏........");
System.out.println("导演:OK,让她来.......");
System.out.println("经理人:导演让你去试戏.......");
this.superStar.moveShw();
System.out.println("XXX,一炮而红.........");
}
}
运行结果
动态代理
动态代理实现方式
被代理者是一个不固定的对象。可能是一个抽象,在代理之前所有的代码都是未知的。利用反射和字节码 技术在运行期间创建代理对象。
JDK动态代理
基于接口实现 被代理者需要实现接口。
JDK动态代理通过反射类Proxy以及InvocationHandler回调接口实现,代理者实现InvocationHandler,在Invoke方法中实现切面进行逻辑增强 。
CGlib 动态代理
对于没有接口的类,CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。
1.jdk动态代理
定义接口:JDKSuperStar
package jdkdyncproxy;
public interface JDKSuperStar
{
public void moveShow();
}
被代理类:
package jdkdyncproxy;
public class Yangmi implements JDKSuperStar
{
public void moveShow()
{
System.out.println("我在快乐的演戏..");
}
}
代理类:JDKProxyHandler
package jdkdyncproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class JDKProxyHandler implements InvocationHandler
{
private Object superStar ;
public JDKProxyHandler(Object obj)
{
this.superStar = obj;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
// Object proxy:要代理的动态代理类--动态生成的
// Method method:动态代理类所有的实现方法
// Object[] args :传的参数
Object proxyObj = method.invoke(this.superStar,args);
return proxyObj;
}
}
测试类:
/*import cglibproxy.CGProxyHandle;
import cglibproxy.Damimi;*/
import jdkdyncproxy.JDKProxyHandler;
import jdkdyncproxy.JDKSuperStar;
import jdkdyncproxy.Yangmi;
import staticproxy.SuperStar;
import staticproxy.SuperStarProxy;
import java.lang.reflect.Proxy;
public class ProxyTest
{
public static void main(String[] args) {
//jdk动态代理
Yangmi yangmi = new Yangmi();
JDKProxyHandler jdkProxyHandler = new JDKProxyHandler(yangmi);
JDKSuperStar jdkSuperStar = (JDKSuperStar)Proxy.newProxyInstance(yangmi.getClass().getClassLoader(),yangmi.getClass().getInterfaces(),jdkProxyHandler);
jdkSuperStar.moveShow();
}
}
若要再代理其他的类,是需要增加相应的实体类,和接口就可以了。
Cglib动态代理
huahua.java
package cglibproxy;
public class huahua
{
public void moveShow()
{
System.out.println("我在快乐的演戏....");
}
}
CGProxyHandle .java
package cglibproxy;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CGProxyHandle implements MethodInterceptor
{
public Object getProxy(Class c)
{
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(c);
enhancer.setCallback((Callback) this);
return enhancer.create();
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable
{
Object proxInst = methodProxy.invokeSuper(o,objects);
return proxInst;
}
}
测试
ProxyTest.java
import cglibproxy.CGProxyHandle;
import cglibproxy.Damimi;
import java.lang.reflect.Proxy;
public class ProxyTest
{
public static void main(String[] args) {
//cglib动态代理
CGProxyHandle cgProxyHandle = new CGProxyHandle();
Damimi damimi = (Damimi) cgProxyHandle.getProxy(Damimi.class);
damimi.moveShow();
}
}