代理功能在现实中也很常见,工厂生产货物,消费者购买商品,按道理消费者可以直接从厂家处购买,但是通常情况下,工厂不会直接销售给消费者,而是委托给代理商进行销售,顾客跟代理商打交道,而不直接与产品实际生产者进行关联,代理商在中间赚取差价。
java中也是实现类似的功能
代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。值得注意的是,代理类和被代理类应该共同实现一个接口,或者是共同继承某个类
jdk动态代理在类实现了接口的情况下使用,cglib在类有继承的情况下使用
1、静态代理
创建1个接口类,1个实体类,1个代理类。
// 测试主类
public class Generic{
public static void main(String[] args) {
// 创建实体类Dog和Cat
Animal dog = new Dog();
// 分别传入Dog和Cat创建代理类
AnimalProxy DogProxy = new AnimalProxy(dog);
// 调用代理类
DogProxy.eat();
DogProxy.drink();
}
}
// 公共接口,定义公共方法
interface Animal{
void eat();
void drink();
}
// 创建实体类Dog,重写Eat方法
class Dog implements Animal{
@Override
public void eat() {
System.out.println("狗吃肉");
}
@Override
public void drink() {
System.out.println("狗喝水");
}
}
// 创建一个代理类,设置一个公共接口的属性,构造方法传入接口类,最后重写Eat、Drink方法,在里面拓展原有方法的功能
class AnimalProxy implements Animal{
private Animal animal;
public AnimalProxy(Animal animal) {
this.animal = animal;
}
@Override
public void drink() {
System.out.println("开始准备食物!");
this.animal.drink();
System.out.println("食物已经吃完啦!");
}
@Override
public void eat() {
System.out.println("开始准备食物!");
this.animal.eat();
System.out.println("食物已经吃完啦!");
}
}
优点是使用静态代理类可以在不修改原有代码的基础上,对原本的程序进行拓展或者重写,缺点是所有的类型都是预先定义好的,不够灵活,如果有多个方法需要添加某个拓展功能,需要重写多个方法,如果有多个接口就要分别写代理类实现。
2.动态代理
jdk动态代理,针对于实现接口的类,创建1个接口类,1个实体类(文中2个体现代码复用性),1个代理类。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Test{
public static void main(String[] args) {
Animal dog = new Dog();
InvocationHandler dogHandler = new Home(dog);
Animal dogAnimal = (Animal) Proxy.newProxyInstance(Dog.class.getClassLoader(),Dog.class.getInterfaces(), dogHandler);
dogAnimal.eat();
dogAnimal.drink();
Plant tree = new Tree();
InvocationHandler treeHandler = new Home(tree);
Plant treePlant = (Plant) Proxy.newProxyInstance(Tree.class.getClassLoader(), Tree.class.getInterfaces(), treeHandler);
treePlant.breath();
}
}
// 创建接口Animal,定义Eat方法
interface Animal{
void eat();
void drink();
}
// 创建接口Plant,定义Breath方法
interface Plant{
void breath();
}
// 创建实体类Dog,实现Animal接口,重写Eat方法
class Dog implements Animal{
@Override
public void eat() {
System.out.println("狗吃肉");
}
@Override
public void drink() {
System.out.println("狗喝水");
}
}
// 创建实体类Tree,实现Plant接口,重写Breath方法
class Tree implements Plant{
@Override
public void breath() {
System.out.println("植物呼吸空气");
}
}
// 创建动态代理实现InvocationHandler接口,创建Object属性target,构造函数传入目标类,重写invoke方法,通过method.invode(target,args)调用target的方法
class Home implements InvocationHandler {
private Object target;
public Home(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始准备食物!");
method.invoke(target,args);
System.out.println("食物已经吃完啦!");
return null;
}
}
cglib动态代理,首先使用maven引入cglib包,创建1个实体类,1个代理类
package org.fssx;
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 Test
{
public static void main( String[] args )
{
MyProxy myProxy = new MyProxy();
Dog dog = (Dog) myProxy.getProxy(Dog.class);
dog.Eat();
}
}
// 被代理实体类
class Dog{
void Eat(){
System.out.println("狗吃肉");
}
}
// 代理类
class MyProxy implements MethodInterceptor{
// 实例化时创建
private final Enhancer enhancer = new Enhancer();
public Object getProxy(Class cls){
enhancer.setSuperclass(cls);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("开始准备食物!");
methodProxy.invokeSuper(o, objects);
System.out.println("食物已经吃完了!");
return null;
}
}