代理模式给原对象提供了一个代理对象,代理对象可以访问原对象的引用,扩展功能,符合设计模式的开闭原则(可以扩展,禁止修改内部功能)。
代理模式有静态代理、动态代理和cglib代理,静态代理一个代理只对应了一个原对象,动态代理利用反射机制,一个代理可以对应多个原对象,cglib代理也可对应多个原对象,动态代理在运行时动态创建一个类实现原对象的接口作为代理类来使用,cglib代理在运行时动态创建一个类继承原对象来带使用。
接口
public interface User {
void sayHello();
}
接口实现
public class TeacherImpl implements User {
public void sayHello() {
System.out.println("I'm teacher");
}
}
代理类(代理类中,我们用代理类的方法sayHello来访问原对象User的sayHello()方法,并且扩展了该方法,这其实就是代理的主要作用--在不修改源代码的情况下,扩展服务功能)
public class UserProxy implements User {
private User user;
public UserProxy(User user){
this.user = user;
}
public void sayHello() {
System.out.println("who are you");
user.sayHello();
System.out.println("ok");
}
}
测试
public static void main(String[] args){
User teacher = new TeacherImpl();
UserProxy teacherUser = new UserProxy(teacher);
teacherUser.sayHello();
}
动态代理相对静态代理较为灵活,一个代理类可以代理多个对象,实际上,可以根据不同的业务来创建不同的代理类
接口
public interface User {
void sayHello();
}
实现类
public class TeacherImpl implements User {
public void sayHello() {
System.out.println("I'm teacher");
}
}
代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class UserProxyFactory {
private Object object;
public UserProxyFactory(Object object){
this.object = object;
}
public Object getProxyInstance(){
return Proxy.newProxyInstance(
object.getClass().getClassLoader(),
object.getClass().getInterfaces(),
new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("who are you?");
Object o = method.invoke(object,args);
System.out.println("ok");
return o;
}
});
}
}
测试
public static void main(String[] args){
User teacher = new TeacherImpl();
UserProxyFactory userProxyFactory = new UserProxyFactory(teacher);
User proxyInstance = (User) userProxyFactory.getProxyInstance();
proxyInstance.sayHello();
}
每个代理对象对应一个调用处理器,当我们调用代理对象的方法时候,他会去调用处理器中找到对应的方法,然后调用它。
动态代理主要依靠Proxy类的newProxyInstance来创建一个代理对象,这个方法一共有三个参数。
第一个参数是被代理类的类加载器,第二个参数是被代理类实现的接口列表,第三个参数是这个代理对象对应的调用处理器,返回的对象使用我们传入的类加载器加载(第一个参数),并且实现了我们传入的接口(第二个参数)。
cglib代理不需要创建接口,cglib代理通过创建一个当前类的子类来实现代理
类方法
public class User {
public void sayHello(){
System.out.println("I'm wyl");
}
}
创建代理对象,设置代理对象的方法拦截器,调用元对象的所有方法 ,都会被方法拦截器拦截
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxy {
public static void main(String[] args){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(User.class);
enhancer.setCallback(new MethodInterceptor(){
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("who are you");
Object result = proxy.invokeSuper(obj, args);
System.out.println("you are handsome");
return result;
}
});
User user = (User) enhancer.create();
user.sayHello();
}
}