AspectJ是编译时织入
AspectJ 5+是类加载时织入
Spring AOP是运行时织入
【动态】CGLIB、JDK动态代理、Spring AOP
【静态】AspectJ、JDK静态代理
静态代理的缺点:
1)一个代理类只为一个接口服务,如果要代理的接口很多,势必要为每一种接口都进行代理,静态代理在程序规模稍大时就无法胜任了。
2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
cglib通过继承的方式实现代理类(Enhancer类的setSuperclass方法),通过Enhancer类的setSuperclass方法织入
JDK只能针对有接口的类的接口方法进行动态代理
扫描二维码关注公众号,回复:
3148612 查看本文章
/**
* JDK代理演示
*/
interface Message {
void send();
}
class MessageImp implements Message {
@Override
public void send() {
System.out.println("send message");
}
public void send2() {
System.out.println("send222222222222222222222");
}
}
public class DynamicProxy implements InvocationHandler {
/**
* 真实的业务对象
*/
private Object target;
/**
* 增强的方法
*/
private boolean connect() {
System.out.println("[消息代理],进行发送消息之前的连接");
return true;
}
/**
* 增强的方法
*/
private void close() {
System.out.println("[消息代理],关闭连接");
}
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
/**
* @param proxy 需要代理的对象
* @param method 要执行的方法的名称
* @param args 要执行的方法的参数
* @return 方法的返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object returnData = null;
if (this.connect()) {
returnData = method.invoke(this.target, args);
this.close();
}
return returnData;
}
/**
* 客户端
* @param args
*/
public static void main(String[] args) {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
Message message = (Message) new DynamicProxy().bind(new MessageImp());
// MessageImp messageImp = (MessageImp) new DynamicProxy().bind(new MessageImp()); error 无法转换成MessageImp类型
message.send();
// messageImp.send(); error
// messageImp.send2(); error
}
}
cglib基于继承来实现代理,无法对static,final类进行代理,也无法对private,static方法进行代理
Spring AOP中代理方式的选择:
如果目标对象实现了接口,则默认采用JDK动态代理
如果目标对象没有实现接口,则采用cglib动态代理
如果目标对象实现了接口,且强制cglib代理,则使用cglib代理(设置如下)