java代理
代理是一种设计模式,其主要作用是对原对象的代理,这样可以在无需修改原对象的类的同时还能对原对象的功能进行增强。
java代理可以分为静态代理和动态代理,在spring中还有cglib代理。我们接下来可以看一下三种代理方式的实现。
一、静态代理:
public interface Star { void perform(); } public class JayZhou implements Star { @Override public void perform() { System.out.println("周杰伦表演"); } } public class JayProxy implements Star{ private Star jayZhou; public JayProxy (Star jayZhou){ this.jayZhou = jayZhou; } @Override public void perform() { System.out.println("经纪人签合同。。。"); jayZhou.perform(); System.out.println("经济人收钱。。。"); } } public class Test { public static void main(String[] args) { Star jay = new JayZhou(); JayProxy proxy = new JayProxy(jay); proxy.perform(); } }
打印:
经纪人签合同。。。
周杰伦表演
经济人收钱。。。
动态代理:也叫jdk代理
public interface Sourceable { void method(); } public class Source implements Sourceable { @Override public void method() { System.out.println("this is source method"); } } //第一种动态代理写法 public class ProxyFactory{ private Sourceable source; public ProxyFactory(){ this.source = new Source(); }; public Sourceable getProxyInstance(){ return (Sourceable)Proxy.newProxyInstance( source.getClass().getClassLoader(), source.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before method"); Object result = method.invoke(source, args); System.out.println("after method"); return result; } }); } } //第二种动态代理写法,其实和第一中是一样的 public class SourceProxy implements InvocationHandler{ private Sourceable source = new Source(); public Sourceable getSourceProxy(){ return (Sourceable)Proxy.newProxyInstance(source.getClass().getClassLoader(), source.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before method"); Object result = method.invoke(source, args); System.out.println("after method"); return result; } } //测试动态代理 public class ProxyTest { public static void main(String[] args) { ProxyFactory proxyFactory = new ProxyFactory(); Sourceable proxy = proxyFactory.getProxyInstance(); proxy.method(); System.out.println("===="); SourceProxy sourceProxy = new SourceProxy(); Sourceable proxy2 = sourceProxy.getSourceProxy(); proxy2.method(); } }
cglib代理:
public class JJ { public void perform(){ System.out.println("来唱一首江南"); } } public class JJProxy implements MethodInterceptor { private Object target; public Object getInstance(Object target){ this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable { System.out.println("经纪人签合同。。。"); proxy.invokeSuper(obj, arg); System.out.println("经纪人签收钱。。。"); return null; } } public class Test { public static void main(String[] args) { JJ jj = new JJ(); JJ proxy = (JJ)new JJProxy().getInstance(jj); proxy.perform(); } }
三种代理方式的说明:
1.静态代理的代理类需要与被代理类实现相同的接口,或者有相同的父类。
其优点是在不改变原有类的情况下,通过创建代理类来对原有类的功能进行增强和代理。在编译时就实现了代理功能。但是如果有不同的类对象需要代理,并且增强的功能一样,那么就会出现很多重复的代码。
2.动态代理是程序在运行时根据需要动态的创建代理类及其实例,来对原有类进行代理,动态代理可以解决代码过多重复的问题。该代理的特点是原有类一定要有实现过接口,不然无法使用动态代理。
3.cglib代理,在spring中用到的一种代理。该代理是通过创建子类对象,来完成代理功能。所以如果该类被final修饰,则无法进行cglib代理。
为什么要使用代理模式?
如果将业务逻辑与业务调用写在一起,这样会造成代码耦合度比较高,不利于维护。通过代理模式可以将方法的调用和业务逻辑解耦,将方法的实现完全隐藏在方法内部。