摘要: 原创出处 https://peijie-sh.gitgub.io 欢迎转载,保留摘要,谢谢!java
代理是Java经常使用的设计模式,代理类经过调用被代理类的相关方法,实现对相关方法加强。好比加入事务、日志、报警发邮件等操做。git
静态代理,就是由程序员手动编写代理类或者用工具生成代理类的代码,再进行编译生成class文件,实现代理。好比简单工厂模式。程序员
用法:spring
缺点: 静态代理要为每一个目标类建立一个代理类,当须要代理的对象太多,那么代理类也变得不少。代理类违背了可重复代理只写一次的原则。编程
为了解决静态代理的缺点,因而引入了动态代理。 它有一个好处,那就是不用写不少代理类,生成的代理类数量是固定的。 通常动态代理分为2种:设计模式
JDK动态代理是JDK自带的,不依赖第三方框架。 它的实现原理,就是利用Java的反射机制,建立一个实现接口的代理类。框架
用法:dom
下面贴个例子ide
接口类:函数
public interface Subject {
public void doSomething();
}
复制代码
实现类:
public class RealSubject implements Subject {
public void doSomething() {
System.out.println("do 了 some thing ...");
}
}
复制代码
代理工厂:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyHandler implements InvocationHandler {
private Object target;
//绑定委托对象,并返回代理类
public Object bind(Object target) {
this.target = target;
//绑定该类实现的全部接口,取得代理类
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy , Method method , Object[] args)throws Throwable {
Object result = null;
//这里就能够进行所谓的AOP编程了
//在调用具体函数方法前,执行功能处理
result = method.invoke(target, args);
//在调用具体函数方法后,执行功能处理
return result;
}
}
复制代码
测试类:
public class TestProxy {
public static void main(String args[]) {
ProxyHandler proxy = new ProxyHandler();
//绑定该类实现的全部接口
Subject sub = (Subject) proxy.bind(new RealSubject());
sub.doSomething();
}
}
复制代码
使用CGLIB代理须要引入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 obj) {
this.targetObject = obj;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(obj.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 ("addUser".equals(method.getName())) {// 过滤方法
checkPopedom();// 检查权限
}
obj = method.invoke(targetObject, args);
return obj;
}
private void checkPopedom() {
System.out.println("检查权限 checkPopedom()!");
}
}
复制代码
public class Test {
public static void main(String[] args) {
Subject sub = (Subject) new CGLibProxy().createProxyObject(new RealSubject());
sub.doSomething();
}
复制代码
JDK动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。 而CGLIB动态代理是利用asm开源包,加载代理对象类的class文件,修改其字节码生成子类来处理。
在 Spring 中,
如何强制使用CGLIB实现AOP?
<aop:aspectj-autoproxy proxy-target-class="true"/>
spring.aop.proxy-target-class=true
JDK动态代理和CGLIB字节码生成的区别?