为其他对象提供一种代理以控制对这个对象的访问。
2. 代理模式涉及到的角色?
<1> 抽象角色:声明真实对象和代理对象的共同接口;
<2> 代理角色:内部含有对真实对象的引用;
<3> 真实角色:最终要引用的角色。
3. 代理类型?
<1> 静态代理
实例说明:
抽象角色:
package com.lxh.proxy;
// 静态代理
public interface HelloWorld {
// 测试方法---无参
public void sayHello();
// 测试方法---有参
public void sayHello(int count);
}
代理角色:
package com.lxh.proxy;
/**
* 静态代理
*/
public class StaticProxy implements HelloWorld {
private HelloWorldImpl hwi;
public StaticProxy(HelloWorldImpl hwi) {
this.hwi = hwi;
}
@Override
public void sayHello() {
hwi.sayHello();
}
public void sayHello(int count){
System.out.println("怼了 "+count+" 次");
}
}
真实角色:
package com.lxh.proxy;
public class HelloWorldImpl implements HelloWorld {
private String str;
public HelloWorldImpl(String s) {
this.str = s;
}
@Override
public void sayHello() {
System.out.println("Hello World:" + this.str);
}
public void sayHello(int count) {
System.out.println("怼了 " + count + " 次");
}
}
测试类:
package com.lxh.proxy;
public class StaticProxyTest {
public static void main(String[] args) {
HelloWorld hw2 = new StaticProxy(new HelloWorldImpl("lxh"));
hw2.sayHello();
hw2.sayHello(4);
}
}
运行结果:
<2> 动态代理
实例说明:
抽象角色:
package com.lxh.proxy;
// 动态代理
public interface HelloWorld {
// 测试方法---无参
public void sayHello();
// 测试方法---有参
public void sayHello(int count);
}
代理角色:
package com.lxh.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理
*/
public class ProxyHandler implements InvocationHandler {
private Object tar;
public ProxyHandler(Object obj){
this.tar = obj;
}
// 绑定委托对象
public Object bind() {
return Proxy.newProxyInstance(tar.getClass().getClassLoader(), tar
.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 返回值
Object obj = null;
/**
* 这里就可以进行所谓的AOP编程了
*/
// 在调用具体函数方法前,执行功能处理
System.out.println("执行方法:\t"+method);
obj = method.invoke(tar, args);
System.out.println("obj:\t"+obj);
// 在调用具体函数方法后,执行功能处理
// 返回
return obj;
}
}
真实角色:
package com.lxh.proxy;
public class HelloWorldImpl implements HelloWorld {
private String str;
public HelloWorldImpl(String s) {
this.str = s;
}
@Override
public void sayHello() {
System.out.println("Hello World:" + this.str);
}
public void sayHello(int count) {
System.out.println("怼了 " + count + " 次");
}
}
测试类:
package com.lxh.proxy;
/**
* 动态代理
*/
public class DynamicProTest {
public static void main(String[] args) {
ProxyHandler proxy = new ProxyHandler(new HelloWorldImpl("lxh"));
HelloWorld hw = (HelloWorld) proxy.bind();
hw.sayHello();
hw.sayHello(3);
}
}
运行结果:
小结:
通过"静态代理"实例可以看出:每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理(即开发过程中的接口比较多),而且,所有的代理操作除了调用的方法不一样之外,其他的操作都一样,则此时肯定是重复代码。解决这一问题最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就应该使用动态代理
"动态代理":动态代理类的字节码在程序运行时可由Java反射机制动态生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。
注意: JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。
补充: cglib动态代理 参考:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html
package com.lxh.proxyOfCglib;
// 动态代理
public interface HelloWorld {
// 测试方法---无参
public void sayHello();
}
package com.lxh.proxyOfCglib;
/**
* 没有实现接口的实现类
*/
public class HelloWorld2 {
// 测试方法---无参
public void sayHello(){
System.out.println("hello...");
}
}
package com.lxh.proxyOfCglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor {
private Object target;
/**
* 创建代理对象
*
* @param target
* @return
*/
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
// 回调方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("事物开始");
proxy.invokeSuper(obj, args);
System.out.println("事物结束");
return null;
}
}
package com.lxh.proxyOfCglib;
public class TestCglib {
public static void main(String[] args) {
CglibProxy cp = new CglibProxy();
HelloWorld2 hw = (HelloWorld2) cp.getInstance(new HelloWorld2());
hw.sayHello();
}
}
运行结果: