您的位置:首页 > 其它

代理模式

2018-03-29 14:24 99 查看
Java的三种代理模式
1.静态代理模式
静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类.

创建接口并实现接口public interface Hello {
void say();
}
public class HelloImpl implements Hello{

@Override
public void say() {
System.out.println("说话");
}

}

创建一个代理对象并实现这个接口public class HelloProxy implements Hello{
private Hello hello; ////接收保存目标对象

public HelloProxy(Hello hello) {
this.hello=hello;
}

@Override
public void say() {
System.out.println("说话之前添加业务逻辑");
hello.say();
System.out.println("说话过后业务逻辑");
}
public static void main(String[] args) {
HelloProxy helloProxy = new HelloProxy(new HelloImpl());
helloProxy.say();
}

}结果:
说话之前添加业务逻辑
说话
说话过后业务逻辑
静态代理总结:
1.可以做到在不修改目标对象的功能前提下,对目标功能扩展.
2.缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.2.动态代理
动态代理有以下特点:
1.代理对象,不需要实现接口
2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
3.动态代理也叫做:JDK代理,接口代理JDK中生成代理对象的API
代理类所在包:java.lang.reflect.Proxy
JDK实现代理只需要使用newProxyInstance方法,但是该方法需要接收三个参数,完整的写法是:
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
注意该方法是在Proxy类中是静态方法,且接收的三个参数依次为:
ClassLoader loader,
:指定当前目标对象使用类加载器,获取加载器的方法是固定的
Class<?>[] interfaces,
:目标对象实现的接口的类型,使用泛型方式确认类型
InvocationHandler h
:事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入
有两种动态代理写法,第一种不实现接口InvocationHandler创建HelloProxypublic class HelloProxy {
private Object object;

public HelloProxy(Object object) {
this.object = object;
}

public Object getInsances() {
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(),
new InvocationHandler() {

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("说话之前添加业务逻辑");
Object o = method.invoke(object, args);
System.out.println("说话过后业务逻辑");
return o;
}
});
}

public static void main(String[] args) {
Hello proxy = (Hello) new HelloProxy(new HelloImpl()).getInsances();
proxy.say();
}

}结果:说话之前添加业务逻辑
说话
说话过后业务逻辑第二种就是HelloProxy实现InvocationHandler接口public class HelloProxy implements InvocationHandler {
private Object object;

public HelloProxy(Object object) {
this.object = object;
}

public Object getInstances() {
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("说话之前添加业务逻辑");
Object invoke = method.invoke(object, args);
System.out.println("说话过后业务逻辑");
return invoke;
}

public static void main(String[] args) {
Hello proxy = (Hello) new HelloProxy(new HelloImpl()).getInstances();
proxy.say();
}

}总结:
代理对象不需要实现目标对象接口,但是目标对象一定要实现接口,否则不能用动态代理3.Cglib代理上面的静态代理和动态代理模式都是要求目标对象是实现一个接口的目标对象,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现代理,这种方法就叫做:Cglib代理Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.
JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口,如果想代理没有实现接口的类,就可以使用Cglib实现.
Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口.它广泛的被许多AOP的框架使用,例如Spring AOP和synaop,为他们提供方法的interception(拦截)
Cglib子类代理实现方法:
1.需要引入cglib的jar文件,cglib.jar
2.引入功能包后,就可以在内存中动态构建子类
3.代理的类不能为final,否则报错
4.目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
创建Hello类public class Hello {
public void say(){
System.out.println("说话");
}
}创建HelloCglib类并实现MethodInterceptor接口public class HelloCglib implements MethodInterceptor{
private Object object;

public HelloCglib(Object object) {
this.object=object;
}

public Object getInstancs(){
Enhancer enhancer=new Enhancer(); //创建加强器,用来创建动态代理类
enhancer.setSuperclass(object.getClass()); //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
enhancer.setCallback(this); //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
return enhancer.create(); // 创建动态代理类对象并返回

}
// 实现回调方法
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
System.out.println("说话之前添加业务逻辑");
arg1.invoke(object, arg2);
System.out.println("说话过后业务逻辑");
return null;
}

public static void main(String[] args) {
Hello instancs =(Hello)new HelloCglib(new Hello()).getInstancs();
instancs.say();
}

}结果:说话之前添加业务逻辑
说话
说话过后业务逻辑
总结:静态代理和动态代理都必须要求目标对象实现接口,而Cglib不需要目标对象实现接口
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: