代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。
第一步,写一个接口。
public interface Mobileable { void updateMobile(String mobile) throws Exception; } 复制代码
第二步,写一个我们要增强的类并实现Mobileable接口。
public class Person implements Mobileable{ private String name; private String mobile; @Override public void updateMobile(String mobile) { this.mobile = mobile; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getMobile() { return mobile; } } 复制代码
第三步,写一个代理类,也实现Mobileable接口并把要增强的对象作为成员变量。
public class PersonProxy implements Mobileable{ private Person person; Pattern mobilePattern = Pattern.compile("1//d{10}"); public PersonProxy(Person person) { this.person = person; } @Override public void updateMobile(String mobile) throws Exception { System.out.println("执行目标方法之前,模拟开始事务 ..."); if(mobile == null || "".equals(mobile)){ throw new Exception("电话号码为空"); } Matcher m = mobilePattern.matcher(mobile); if (m.matches()){ System.out.println("电话号码格式正确"); }else{ throw new Exception("电话号码格式错误"); } // 执行目标方法,并保存目标方法执行后的返回值 person.updateMobile(mobile); System.out.println("执行目标方法之后,模拟结束事务 ..."); } } 复制代码
第四步,测试。
public class TestCase { public static void main(String[] args){ Person person = new Person(); PersonProxy personProxy = new PersonProxy(person); person.setName("123"); try { // personProxy.updateMobile(null); // personProxy.updateMobile("123"); personProxy.updateMobile("12345678901"); } catch (Exception e) { e.printStackTrace(); } System.out.println(person.getName()); System.out.println(person.getMobile()); } } 复制代码
JDK代理又称接口代理。JDK代理主要是通过JDK自带的API实现的。用的是reflect包下的Proxy类的newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法。
利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
第一步,写一个接口。
public interface IAnimal { void eat(String food); void speak(String language); } 复制代码
第二步,实现这个接口。
public class Cat implements IAnimal{ @Override public void eat(String food) { System.out.println(this.getClass().getSimpleName() + " eats " + food); } @Override public void speak(String language) { System.out.println(this.getClass().getSimpleName() + " speaks " + language); } } 复制代码
public class Dog implements IAnimal{ @Override public void eat(String food) { System.out.println(this.getClass().getSimpleName() + " eats " + food); } @Override public void speak(String language) { System.out.println(this.getClass().getSimpleName() + " speaks " + language); } } 复制代码
第三步,实现一个自定义拦截器,实现InvocationHandler接口。
public class AnimalActionHandler implements InvocationHandler { private Object object; public AnimalActionHandler(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(object.getClass().getSimpleName()+"."+method.getName()+"()执行之前"); Object invoke = method.invoke(object, args); System.out.println(object.getClass().getSimpleName()+"."+method.getName()+"()执行之后"); return invoke; } } 复制代码
第四步,测试。
public class TestCase { public static void main(String[] args) { IAnimal cat = (IAnimal) Proxy.newProxyInstance(Cat.class.getClassLoader(), new Class[]{IAnimal.class}, new AnimalActionHandler(new Cat())); IAnimal dog = (IAnimal) Proxy.newProxyInstance(Dog.class.getClassLoader(), new Class[]{IAnimal.class}, new AnimalActionHandler(new Dog())); cat.eat("fish"); cat.speak("miao"); dog.eat("bone"); dog.speak("wang"); } } 复制代码
CGLIB代理又称子类代理。利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
第一步,写需要被代理的类。
public class Person { private String name; private String mobile; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } } 复制代码
第二步,写一个实现了MethodInterceptor接口的代理类。
public class PersonProxyFactory implements MethodInterceptor{ private final static String SET_MOBILE = "setMobile(Ljava/lang/String;)V"; Pattern mobilePattern = Pattern.compile("1//d{10}"); private Object target; public PersonProxyFactory(Object target) { this.target = target; } > public Object newProxyInstance(){ Enhancer en = new Enhancer(); // 设置要代理的目标类 en.setSuperclass(target.getClass()); // 设置要代理的拦截器 en.setCallback(this); // 生成代理类的实例 return (Person) en.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { String name = methodProxy.getSignature().toString(); Object rvt; if (SET_MOBILE.equals(name)){ System.out.println("执行目标方法之前,模拟开始事务 ..."); if(objects[0] == null || "".equals(objects[0])){ throw new Exception("电话号码为空"); } Matcher m = mobilePattern.matcher(objects[0].toString()); if (m.matches()){ System.out.println("电话号码格式正确"); }else{ throw new Exception("电话号码格式错误"); } // 执行目标方法,并保存目标方法执行后的返回值 rvt = methodProxy.invokeSuper(o, objects); System.out.println("执行目标方法之后,模拟结束事务 ..."); }else { // 执行目标方法,并保存目标方法执行后的返回值 rvt = methodProxy.invokeSuper(o, objects); } return rvt; } } 复制代码
第三步,测试。
public class TestCase { public static void main(String[] args) { Object o = new Person(); > PersonProxyFactory personProxyFactory = new PersonProxyFactory(o); Person person = (Person) personProxyFactory.newProxyInstance(); > // person.setName("123"); // person.setName("yellowdoge"); person.setMobile(null); // person.setMobile("12345678901"); // System.out.println(person.getName()); System.out.println(person.getMobile()); // System.out.println(person.getClass()); } } 复制代码