自理解:通过JDK/Cglib
拦截被代理类对象
,并对其进行修改使代理类拥有所有被代理类实现的接口内方法
;JDK原理:
被代理类需要接口
,使用JDK自带方法Proxy获取代理对象 通过反射获取其方法;Cglib原理:
被代理类无须接口
,引入Cglib通过指定方法获取代理对象.动态代理是在程序运行时通过反射机制动态创建的。
JDK动态代理:
通过JDK自带的方法Proxy获取代理对象
涉及反射
调用Proxy类的静态方法newProxyInstance即可,该方法会返回代理类对象
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h ) 接收的三个参数依次为:
ClassLoader loader:指定当前目标对象使用类加载器,写法固定
Class<?>[] interfaces:目标对象实现的接口的类型,写法固定
InvocationHandler h:提供的执行被代理角色方法的方法。
缺点:
可以看出静态代理和JDK代理有一个共同的缺点,就是目标对象必须实现一个或多个接口,如果没有,则可以使用Cglib代理。
public interface ISinger { void sing(); void sings(); } /** * 目标对象实现了某一接口 */ public class Singer implements ISinger{ public void sing(){ System.out.println("唱一首歌"); } public void sings(){ System.out.println("唱二首歌"); } } public class Test{ public static void main(String[] args) { //new被代理类对象 Singer target = new Singer(); //通过lambda创建代理类对象proxy ISinger proxy = (ISinger) Proxy.newProxyInstance( target.getClass().getClassLoader(),target.getClass().getInterfaces(),new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("向观众问好"); //执行目标对象方法 Object returnValue = method.invoke(target, args); System.out.println("谢谢大家"); return returnValue; } }); //输出方法,可直接调用被代理类对象中的方法并且经过代理类拦截修改后输出 proxy.sing(); proxy.sings(); } } //若不适应lambda则可以创建代理类-------------------------------------- //代理类 public class Behavior { //代理对象接口 private SellHours sellHours; //带参构造器 Behavior(SellHours sellHours){ this.sellHours = sellHours; } //JDK内proxy方法: public Object getSellHours(){ //指定当前目标对象使用类加载器,写法固定 ClassLoader classLoader = sellHours.getClass().getClassLoader(); //目标对象实现的接口的类型,写法固定 Class<?>[] interfaces = sellHours.getClass().getInterfaces(); //提供的执行被代理角色方法的方法 InvocationHandler invocationHandler = new InvocationHandler(){ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //调用执行部分: System.out.println("进入动态代理:::"); //通过反射获取对象方法 Object invoke = method.invoke(sellHours); //返回值 return invoke; } }; return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler); }; } //测试 public class Test { public static void main(String[] args) { //创建代理对象并赋值被代理类对象 Behavior behavior = new Behavior(new Landlord()); //使用代理对象内方法获取被代理类方法 SellHours sellHours = (SellHours) behavior.getSellHours(); //执行 sellHours.getName(); } }
Cglib代理:
前提条件:
需要
引入cglib的jar文件
,由于Spring的核心包中已经包括了Cglib功能,所以也可以直接引入spring-core-3.2.5.jar
目标类不能为
final
目标对象的方法如果为
final/static
,那么就不会被拦截,即不会执行目标对象额外的业务方法
/** * 目标对象,没有实现任何接口 */ public class Singer{ public void sing() { System.out.println("唱一首歌"); } } /** * Cglib子类代理工厂:这里的代码也非常固定,只有部分是需要自己写出--------- * 创建代理类并实现Cglib中的MethodInterceptor接口 */ public class ProxyFactory implements MethodInterceptor{ // 维护目标对象 private Object target; public ProxyFactory(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(); } //重写Cglib中的方法 @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { //调用执行部分:-------------------- System.out.println("向观众问好"); //通过反射执行目标对象的方法 Object returnValue = method.invoke(target, args); System.out.println("谢谢大家"); //返值 return returnValue; } } /** * 测试类 */ public class Test{ public static void main(String[] args){ //目标对象 Singer target = new Singer(); //代理对象 Singer proxy = (Singer)new ProxyFactory(target).getProxyInstance(); //执行代理对象的方法 proxy.sing(); } }