Java的三种代理模式

1.代理模式是什么?

代理模式是对目标对象访问的另一种方式,通过代理对象访问目标对象,这样做的好处是,可以在原来业务逻辑不变的情况下增加其他功能。

现实中的例子有很多,比如租房,租车等等

代理模式的关键点是:代理对象与目标对象.代理对象是对目标对象的扩展,并会调用目标对象

2.代理模式的实现分为静态代理和动态代理,其中动态代理又分为jdk代理和CGlib代理

2.1.静态代理

静态代理的实现需要和被代理对象实现相同接口,缺点是,每增加一种代理,就需要创建一个类,后期维护难度增加。

静态代理的实现方式如下:

接口类:ICarDao

public interface ICarDao { public void byCar(); }

接口实现类:CarDaoImpl

import com.example.demo.dao.ICarDao; public class CarDaoImpl implements ICarDao { @Override public void byCar() { System.out.println("买大众汽车!!"); } }

静态代理类:CarProxy

import com.example.demo.dao.ICarDao; public class CarProxy implements ICarDao { private ICarDao target; public CarProxy(ICarDao target){ this.target=target; } @Override public void byCar() { System.out.println("交代理费!!"); target.byCar(); } }

测试类:

public class DemoApplication { public static void main(String[] args) { //静态代理方式 ICarDao iCarDao=new CarDaoImpl(); CarProxy carProxy=new CarProxy(iCarDao); carProxy.byCar(); } }

2.2.动态代理-jdk代理

代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用jdk动态代理

代理工厂类

import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class DynamicProxy { private Object target; public DynamicProxy(Object target){ this.target=target; } public Object getInstance(){ return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { /** * method: 代理类需要被调用的方法 * args: 动态代理类方法被调用时传入的参数 * proxy: 动态代理类自身,一般无用 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("交代理费!!"); Object object=method.invoke(target,args); System.out.println("受理完成!!"); return object; } }); } }

测试类

public class DemoApplication { public static void main(String[] args) { //动态jdk代理方式 ICarDao iCarDao=new CarDaoImpl(); ICarDao dynamicProxy = (ICarDao) new DynamicProxy(iCarDao).getInstance(); dynamicProxy.byCar(); } }

2.3.cglib动态代理

上面的静态代理和动态代理模式都是要求目标对象是实现一个接口的目标对象,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现代理,这种方法就叫做:Cglib代理

Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.

被代理类

import com.example.demo.dao.ICarDao; public class HouseDaoImpl { public void buyHouse() { System.out.println("买北京的二居房子!!"); } }

cglib代理工

import org.aopalliance.intercept.MethodInvocation; 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 CGlibProxy implements MethodInterceptor { private Object target; public CGlibProxy(Object target){ this.target=target; } //给目标对象创建一个代理对象 public Object getProxyInstance(){ //1.工具类 Enhancer en = new Enhancer(); //2.设置父类 en.setSuperclass(target.getClass()); //3.设置回调函数 en.setCallback(this); //4.创建子类(代理对象) return en.create(); } /** * method: 代理类需要被调用的方法 * objects: 动态代理类方法被调用时传入的参数 * o: 动态代理类自身,一般无用 */ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("交代理费!!"); //执行目标对象的方法 Object object=method.invoke(target,objects); System.out.println("受理完成!!"); return object; } }

测试类

public class DemoApplication { public static void main(String[] args) { //动态cglib代理方式 HouseDaoImpl houseDaoImpl=new HouseDaoImpl(); HouseDaoImpl cGlibProxy = (HouseDaoImpl) new CGlibProxy(houseDaoImpl).getProxyInstance(); cGlibProxy.buyHouse(); } }

springAop的实现就是用的动态代理的方式,如果加入容器的目标对象有实现接口,用JDK代理,如果目标对象没有实现接口,用Cglib代理