特征:代理类和委托类有同样的接口,代理类主要为委托类预处理消息、过滤消息、把消息转发给委托类、以及事后处理消息等,代理类的本身并不能实现特定功能,代理类通过调用委托类对象的相应方法来提供特殊的服务。
按照代理的创建时期可分为两种:静态代理和动态代理
1、静态代理(class文件在运行之前已经生成)
package com.ifs.proxy;
public interface SimpleService {
public void add();
public void del();
}
package com.ifs.proxy;
public class SimpleServiceImpl implements SimpleService{
public void add() {
System.out.println("add()----------------");
}
public void del() {
System.out.println("del()----------------");
}
}
package com.ifs.proxy.state;
import com.ifs.proxy.SimpleService;
public class StaticProxy implements SimpleService {
private SimpleService simpleService;
public StaticProxy(SimpleService simpleService) {
this.simpleService = simpleService;
}
public void add() {
System.out.println("---------------------->before add()");
this.simpleService.add();
System.out.println("---------------------->after add()");
}
public void del() {
System.out.println("---------------------->before del()");
this.simpleService.del();
System.out.println("---------------------->after del()");
}
}
测试代码:
package com.ifs.proxy.state;
import com.ifs.proxy.SimpleServiceImpl;
public class TestStaticProxy {
public static void main(String[] args) {
StaticProxy proxy = new StaticProxy(new SimpleServiceImpl());
proxy.add();
proxy.del();
}
}
动态代理:动态代理类的字节码在程序运行时由Java反射机制动态生成,既简化的编程工作又提高了软件系统的可扩展性,因为Java反射机制可以生成任意类型的动态代理类,java.lang.reflect 中Proxy类和InvocationHandler接口提高动态生成代码类的能力。
2、动态代理 JDK方式 (值针对存在实现接口的类)
复用之前的 SimpleService类和SimpleServiceImpl类
package com.ifs.proxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKProxy implements InvocationHandler{
private Object targetObject;
public Object newProxy(Object targetObject) {//将目标对象传入进行代理
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(), this);//返回代理对象
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
checkPression();//一般我们进行逻辑处理的函数比如这个地方是模拟检查权限
Object ret = null; // 设置方法的返回值
ret = method.invoke(targetObject, args); //调用invoke方法,ret存储该方法的返回值
return ret;
}
private void checkPression() {//模拟检查权限的例子
System.out.println(">>检查权限 checkPression()!");
}
}
测试代码:
package com.ifs.proxy.jdk;
import com.ifs.proxy.SimpleService;
import com.ifs.proxy.SimpleServiceImpl;
public class TestJDKProxy {
public static void main(String[] args) {
JDKProxy proxy = new JDKProxy();
SimpleService simple = (SimpleService) proxy.newProxy(new SimpleServiceImpl());
simple.add();
}
}
3、动态代理 CGLIB
package com.ifs.proxy.cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGLIBProxy implements MethodInterceptor {
private Object targetObject;// CGLib需要代理的目标对象
public Object createProxyObject(Object targetObject) {
this.targetObject = targetObject;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetObject.getClass());
enhancer.setCallback(this);
Object proxyObj = enhancer.create();
return proxyObj;// 返回代理对象
}
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object obj = null;
if ("add".equals(method.getName())) {// 过滤方法
checkPression();// 检查权限
}
obj = method.invoke(targetObject, args);
return obj;
}
private void checkPression() {
System.out.println(">>检查权限 checkPression()!");
}
}
测试代码:
package com.ifs.proxy.cglib;
import com.ifs.proxy.SimpleService;
import com.ifs.proxy.SimpleServiceImpl;
public class TestCGLIBProxy {
public static void main(String[] args) {
SimpleService simple = (SimpleService) new CGLIBProxy().createProxyObject(new SimpleServiceImpl());
simple.add();
simple.del();
}
}
两者动态代理的区别:
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。