代理模式
动态代理动态的生成代理对象,对满足条件的目标对象皆可以生成代理代理对象,
没有静态代理一个目标类一个代理类的问题
解耦合
JDK动态代理
需要目标类有实现接口
代理类与目标类实现相同接口
接口
package testJdkProxy; //jdk动态代理必须使用接口 public interface JDKProxy { public void sayHelloWorld(); }
实现类
package testJdkProxy; //接口实现,真实主题实现类 public class ImplementClass implements JDKProxy { @Override public void sayHelloWorld() { // TODO Auto-generated method stub System.out.println("hello world"); } }
设置代理
package testJdkProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; //代理,代理操作类 public class DynamicProxy implements InvocationHandler{ //真实对象 (通过实现类实现) private Object target=null; //建立代理对象和真实对象之间的关系 /** * * @param target 真实对象 * @return 代理对象 */ //接受真实主题实现类(目标对象),把代理对象下挂在接口下 生成下挂后的代理对象来实例化接口 public Object bind(Object target) { //保存真实对象,invoke里面会用到 实例化的真实主题实现类 对象——>指向被代理的真实主题 this.target=target; return Proxy.newProxyInstance( //实现类的类加载器 实现类所实现的接口 代理对象 ——>把代理对象下挂在接口下 target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } //代理逻辑 /** * @param proxy 代理对象 * @param method 当前调度方法 * @param args 当前方法参数 * @return 代理结果返回 * @throws Throwable 异常 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub System.out.println("进入代理逻辑方法"); System.out.println("在调度真实对象之前的服务--------"); //------------------------------------------------------------------执行前业务逻辑 Object object=method.invoke(target, args); //相当于调用sayhelloworld方法 //---------------------------------------------------------------------执行后业务逻辑 System.out.println("在调度真实对象之后的服务"); //invoke的返回值 return object; } }
测试
package testJdkProxy; public class ToTest { public static void main(String[] args) { new ToTest().testJdkProxy(); } public void testJdkProxy() { //创建代理 DynamicProxy jdk=new DynamicProxy(); //绑定关系,实例化接口,下挂代理JDKProxy接口下,通过代理实例化接口对象 JDKProxy pro=(JDKProxy)jdk.bind(new ImplementClass()); //此时JDKProxy对象已经是一个代理对象,调用方法的时候,他会自动进入代理的逻辑方法invoke里 重复的业务逻辑不用额外手动调用 pro.sayHelloWorld(); } }
通过bind方法绑定代理关系,实例化接口对象,调用方法时自动转入 代理逻辑invoke方法
CGLIB动态代理
只需要一个非抽象类实现MethodInterceptor
使用:
过程:被代理的类——创建代理——使用
依赖:第三方包 要用到 cglib-nodep-2.2.jar 包
实现 代理要implements MethodInterceptor
原理 Cglib代理可以对任何类生成代理,代理的原理是对目标对象进行继承代理,
注意 如果目标对象,被final修饰了,那么该类似无法被cglib代理的
目标类
package testCGLIBOproxy; public class ProxyedClass { public void sayHello() { System.out.println("hellloworld"); } }
代理类
package testCGLIBOproxy; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; //CGLIB不需要提供接口,只需要一个非抽象类就能实现动态代理 public class CglibProxyExample implements MethodInterceptor { /** * 生成代理对象 * @param cla——Class类 * @return Class类的CGLIB代理对象 */ public Object getProxy(Class cla) { //CGLIB enhancer 增强类对象 加强者 Enhancer enhancer=new Enhancer(); //设置代理谁 setSuperclass设置超类 要继承的目标对象 enhancer.setSuperclass(cla); //setCallback设置代理类 定义代理逻辑对象为当前对象,要求当前对象实现MethodInterceptor方法 enhancer.setCallback(this); //生成并返回代理对象 return enhancer.create(); } /** * 代理逻辑方法 * @param arg0代理对象 * @param arg1方法 * @param arg2方法参数 * @param arg3方法代理 * @return 代理逻辑返回 * */ @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { // TODO Auto-generated method stub System.out.println("调用真实对象前"); //反射调用真实对象方法 传参数给它 Object result=arg3.invokeSuper(arg0,arg2); //调用真实对象后 System.out.println("调用真实对象后"); return result; } }
测试类
package testCGLIBOproxy; public class TestClass { public static void main(String[] args) { new TestClass().testCGLIB(); } public void testCGLIB() { //创建代理对象 CglibProxyExample cep=new CglibProxyExample(); //通过代理实例化被代理对象类 ProxyedClass obj=(ProxyedClass)cep.getProxy(ProxyedClass.class); //与代理关联后,调用方法时,自动进入代理逻辑intercept方法 obj.sayHello(); } }
作者: deity-night
出处: https://www.cnblogs.com/deity-night/
关于作者:码农
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 原文链接 如有问题, 可邮件(***@163.com)咨询.