java代理,静态代理、jdk代理、cglib代理、Aspectj
我实在接触spring的时候才接触到代理这个东西的,一直想整理一下笔记。
什么是代理模式:代理模式是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能。简单来说就是要创建一个新的对象,我们通过这个新的代理对象来操作目标对象。
例如我们租房子,我们可以直接和房东谈,房东其实就是我们的目标对象。但是有时候房东没空理你,所以他们就委托一个中介公司来代他和我们谈,这时候中介公司就可能会搞小动作,例如水电费收贵点,房租收贵1000,这就是所谓的增强操作。
代理的实现有4种:静态代理、jdk代理、cglib代理、Aspectj
1、静态代理
静态代理其实就是你自己写一个代理对象的类。就像下面的 Intermediary
package com.hongcheng.dubbo_api.producer; /** 房东,一个接口 */
interface Landlord{
/** 出租房子 */
void rentHouse();
} /** 包租婆,具体实现 */
class LandlordWoman implements Landlord{
/** 出租房子 */
@Override
public void rentHouse(){
System.out.println("包租婆 ====> 房子800租给你了");
}
} /**
* 中介公司,这就是代理类
* */
class Intermediary implements Landlord{
private Landlord landlord;
public Intermediary(Landlord landlord) {
this.landlord = landlord;
}
/** 出租房子 */
@Override
public void rentHouse() {
System.out.println("中介公司 ====> 房子1000出租,我要赚200");
this.landlord.rentHouse();
}
} /**
* 测试
* */
public class StaticProxy {
public static void main(String[] args) {
// 要有一个包租婆
Landlord landlordWoman = new LandlordWoman();
// 包租婆委托给中介公司
Intermediary intermediary = new Intermediary(landlordWoman);
// 中介公司出租房子给各位韭菜
intermediary.rentHouse();
}
}
静态代理优点:
- 可以对目标类的每个方法都做不同的处理,进行更细致的处理。
静态代理缺点:
- 必须手动重写目标类的所有方法,如果目标类方法过多,编写会很麻烦。
- 如果目标类的方法修改了,代理类也必须同步修改,维护麻烦。
2、 jdk代理
jdk代理这是一种动态代理,不需要我们自己去撸这个一个代理类,由jdk的api来帮我们创建这个类,我们只是要设计一下要怎么代理就好
package com.hongcheng.dubbo_api; import junit.framework.TestCase; import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /** 房东,一个接口 */
interface Landlord{
/** 出租房子 */
void rentHouse();
} /** 包租婆,具体实现 */
class LandlordWoman implements Landlord {
/** 出租房子 */
@Override
public void rentHouse(){
System.out.println("包租婆 ====> 房子800租给你了");
}
}
/**
* 测试
* */
public class AppTest extends TestCase { public static void main(String[] args) throws IOException {
/** 我们的目标对象 */
LandlordWoman hongcheng = new LandlordWoman();
/** 我们目标对象的类加载器 */
ClassLoader classLoader = hongcheng.getClass().getClassLoader();
/** 我们目标对象实现的接口 */
Class<?>[] interfaces = hongcheng.getClass().getInterfaces();
/***
* 创建代理对象
* @param classLoader 类加载器,一般用我们目标对象的类加载器
* @param interfaces 我们目标对象实现的接口
* @param InvocationHandler 我们要对目标对象所有方法做的增强处理
* */
Object instance = Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
/***
* 我们对目标对象的所有方法做的增强处理。
* @param proxy jdk帮我们创建的代理对象
* @param method 我们自己的目标对象的方法
* @param args 我们目标对象方法的调用参数
* */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理开始");
System.out.println("中介公司 ====> 房子1000出租,我要赚200");
// 这里要记住,invoke方法传入的对象是我们的目标对象,不是代理对象
Object invoke = method.invoke(hongcheng);
System.out.println("代理结束,结果===>" + invoke);
return invoke;
}
}); Landlord hong = (Landlord)instance;
hong.rentHouse();
// 这里阻塞程序是为了用工具将代理对象的class弄成.class文件
System.in.read();
} }
jdk代理优点:
- 只需要写一个对所有方法的增强处理就可以,jdk的api会自动处理所有方法,不管后面你怎么更改目标类,代理类的创建的代码都不用改变。
jdk代理缺点:
- 不能更细致的处理个别方法,所有方法的增强处理都是一样的。
- 目标类必须实现一个接口
让我们来看看jdk帮我们生成的代理对象是咋样的先:
$Proxy0 就是我们的代理对象:
特点:
继承Proxy类,实现了我们的Landlord接口
每个方法的调用实际上都是调用我们写的那个匿名内部类 InvocationHandler 的invoke方法,将我们原本的方法和参数传入。
package com.hongcheng.dubbo_api; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException; final class $Proxy0 extends Proxy implements Landlord {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0; public $Proxy0(InvocationHandler var1) {
super(var1);
} static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.hongcheng.dubbo_api.Landlord").getMethod("rentHouse");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
} public final boolean equals(Object var1) {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final String toString() {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final int hashCode() {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final void rentHouse() {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
}
匿名内部类,增强方法的实现。
package com.hongcheng.dubbo_api; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; final class AppTest$1 implements InvocationHandler {
AppTest$1(LandlordWoman var1) {
this.val$hongcheng = var1;
} public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理开始");
System.out.println("中介公司 ====> 房子1000出租,我要赚200");
Object invoke = method.invoke(this.val$hongcheng);
System.out.println("代理结束,结果===>" + invoke);
return invoke;
}
}
3、cglib代理
cglib 就是 Code Generator Library ,是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架(Spring、dynaop)中,用以提供方法拦截操作。Hibernate作为一个比较受欢迎的ORM框架,同样使用CGLIB来代理单端(多对一和一对一)关联(延迟提取集合使用的另一种机制)。
要用cglib需要引入jar包,这里我用maven
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
package com.hongcheng.dubbo_api; import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; import java.io.IOException;
import java.lang.reflect.Method;
/** 房东,一个接口 */
interface Landlord{
/** 出租房子 */
void rentHouse();
}
/** 包租婆,具体实现 */
class LandlordWoman implements Landlord {
/** 出租房子 */
@Override
public void rentHouse(){
System.out.println("包租婆 ====> 房子800租给你了");
}
public final void finalMethod(){
System.out.println("finalMethod ====> 执行了");
}
public static void staticMethod(){
System.out.println("staticMethod ====> 执行了");
}
public void privateMethod1(){
System.out.println("privateMethod1 ====> 执行了");
this.privateMethod2();
}
private void privateMethod2(){
System.out.println("privateMethod2 ====> 执行了");
}
}
/***
* 测试
* */
public class CglibProxy {
public static void main(String[] args) throws IOException {
// 一个很重要的对象,用来生成代理对象,翻译过来就是“增强器”,和jdk代理的Proxy类似功能
Enhancer enhancer = new Enhancer();
// 设置代理对象的父类,这是必须步骤
enhancer.setSuperclass(LandlordWoman.class);
// 设置回调,其实就是增强处理对象,每次调用代理的方法,都会回调调用intercept方法
enhancer.setCallback(new MethodInterceptor() {
/**
* @param proxyObj 代理对象
* @param method 目标类的方法
* @param args 方法的参数
* @param methodProxy 代理对象的方法
* */
@Override
public Object intercept(Object proxyObj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("代理开始");
System.out.println("中介公司 ====> 房子1000出租,我要赚200");
/**
* methodProxy.invokeSuper(proxyObj, args);
* 这种方法使用的是代理对象的方法调用,传入的也是代理对象,但最后还是调用我们自己的目标方法
* */
Object invoke = methodProxy.invokeSuper(proxyObj, args);
/**
* method.invoke(new LandlordWoman(), args);
* 这种方法使用的是我们目标对象的方法调用,传入的是目标对象,需要自己传入一个目标类的实例
* */
// Object invoke2 = method.invoke(new LandlordWoman(), args);
System.out.println("代理结束,结果===>" + invoke);
return invoke;
}
});
// 创建代理对象
LandlordWoman proxy= (LandlordWoman) enhancer.create();
proxy.rentHouse();
proxy.finalMethod();
proxy.privateMethod1();
proxy.staticMethod();
// 这里阻塞程序是为了用工具将代理对象的class弄成.class文件
System.in.read();
}
}
cglib代理优点:
- 只需要写一个对所有方法的增强处理就可以,cglib的api会自动处理所有方法,不管后面你怎么更改目标类,代理类的创建的代码都不用改变。
- 目标类可以不实现任务接口。
- Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类,性能上比较好
cglib代理缺点:
- 不能更细致的处理个别方法,所有方法的增强处理都是一样的。
- 目标类必须实现一个接口
- 代理的类不能为final,否则报错
- 目标对象的方法如果为final或static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
看看他生成后的代理对象内容是怎样,代码有点长
代理对象是直接继承自我们的目标对象的。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// package com.hongcheng.dubbo_api; import java.lang.reflect.Method;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; public class LandlordWoman$$EnhancerByCGLIB$$df42a67d extends LandlordWoman implements Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$rentHouse$0$Method;
private static final MethodProxy CGLIB$rentHouse$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$privateMethod1$1$Method;
private static final MethodProxy CGLIB$privateMethod1$1$Proxy;
private static final Method CGLIB$equals$2$Method;
private static final MethodProxy CGLIB$equals$2$Proxy;
private static final Method CGLIB$toString$3$Method;
private static final MethodProxy CGLIB$toString$3$Proxy;
private static final Method CGLIB$hashCode$4$Method;
private static final MethodProxy CGLIB$hashCode$4$Proxy;
private static final Method CGLIB$clone$5$Method;
private static final MethodProxy CGLIB$clone$5$Proxy; public LandlordWoman$$EnhancerByCGLIB$$df42a67d() {
CGLIB$BIND_CALLBACKS(this);
} static {
CGLIB$STATICHOOK1();
} public final boolean equals(Object var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
} if (var10000 != null) {
Object var2 = var10000.intercept(this, CGLIB$equals$2$Method, new Object[]{var1}, CGLIB$equals$2$Proxy);
return var2 == null ? false : (Boolean)var2;
} else {
return super.equals(var1);
}
} public final String toString() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
} return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy) : super.toString();
} public final int hashCode() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
} if (var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$hashCode$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.hashCode();
}
} protected final Object clone() throws CloneNotSupportedException {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
} return var10000 != null ? var10000.intercept(this, CGLIB$clone$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy) : super.clone();
} public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
LandlordWoman$$EnhancerByCGLIB$$df42a67d var10000 = new LandlordWoman$$EnhancerByCGLIB$$df42a67d;
switch(var1.length) {
case 0:
var10000.<init>();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
default:
throw new IllegalArgumentException("Constructor not found");
}
} public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
LandlordWoman$$EnhancerByCGLIB$$df42a67d var10000 = new LandlordWoman$$EnhancerByCGLIB$$df42a67d();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
} public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
LandlordWoman$$EnhancerByCGLIB$$df42a67d var10000 = new LandlordWoman$$EnhancerByCGLIB$$df42a67d();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
} public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
default:
}
} public final void rentHouse() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
} if (var10000 != null) {
var10000.intercept(this, CGLIB$rentHouse$0$Method, CGLIB$emptyArgs, CGLIB$rentHouse$0$Proxy);
} else {
super.rentHouse();
}
} public final void privateMethod1() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
} if (var10000 != null) {
var10000.intercept(this, CGLIB$privateMethod1$1$Method, CGLIB$emptyArgs, CGLIB$privateMethod1$1$Proxy);
} else {
super.privateMethod1();
}
} public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
} public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
MethodInterceptor var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
default:
var10000 = null;
} return var10000;
} public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0};
} public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
} public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
} final int CGLIB$hashCode$4() {
return super.hashCode();
} final boolean CGLIB$equals$2(Object var1) {
return super.equals(var1);
} final Object CGLIB$clone$5() throws CloneNotSupportedException {
return super.clone();
} final String CGLIB$toString$3() {
return super.toString();
} public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -1702390808:
if (var10000.equals("privateMethod1()V")) {
return CGLIB$privateMethod1$1$Proxy;
}
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$5$Proxy;
}
break;
case 1194948270:
if (var10000.equals("rentHouse()V")) {
return CGLIB$rentHouse$0$Proxy;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$2$Proxy;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$3$Proxy;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return CGLIB$hashCode$4$Proxy;
}
} return null;
} static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("com.hongcheng.dubbo_api.LandlordWoman$$EnhancerByCGLIB$$df42a67d");
Class var1;
Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$equals$2$Method = var10000[0];
CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
CGLIB$toString$3$Method = var10000[1];
CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
CGLIB$hashCode$4$Method = var10000[2];
CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4");
CGLIB$clone$5$Method = var10000[3];
CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
var10000 = ReflectUtils.findMethods(new String[]{"rentHouse", "()V", "privateMethod1", "()V"}, (var1 = Class.forName("com.hongcheng.dubbo_api.LandlordWoman")).getDeclaredMethods());
CGLIB$rentHouse$0$Method = var10000[0];
CGLIB$rentHouse$0$Proxy = MethodProxy.create(var1, var0, "()V", "rentHouse", "CGLIB$rentHouse$0");
CGLIB$privateMethod1$1$Method = var10000[1];
CGLIB$privateMethod1$1$Proxy = MethodProxy.create(var1, var0, "()V", "privateMethod1", "CGLIB$privateMethod1$1");
} final void CGLIB$rentHouse$0() {
super.rentHouse();
} private static final void CGLIB$BIND_CALLBACKS(Object var0) {
LandlordWoman$$EnhancerByCGLIB$$df42a67d var1 = (LandlordWoman$$EnhancerByCGLIB$$df42a67d)var0;
if (!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if (var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if (var10000 == null) {
return;
}
} var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
} } final void CGLIB$privateMethod1$1() {
super.privateMethod1();
}
}
增强内部类的代码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// package com.hongcheng.dubbo_api; import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; final class CglibProxy$1 implements MethodInterceptor {
CglibProxy$1() {
} public Object intercept(Object proxyObj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("代理开始");
System.out.println("中介公司 ====> 房子1000出租,我要赚200");
Object invoke = methodProxy.invokeSuper(proxyObj, args);
System.out.println("代理结束,结果===>" + invoke);
return invoke;
}
}
在Spring的AOP编程中:
如果加入容器的目标对象有实现接口,用JDK代理
如果目标对象没有实现接口,用Cglib代理
4、Aspectj
Aspectj实际上他是一种静态代理,因为Aspectj是在编译代码的时候,将你的增强代码写入你的业务代码中,而不是去创建一个代理类。
- Aspectj并不是动态的在运行时生成代理类,而是在编译的时候就植入代码到class文件
- 由于是静态织入的,所以性能相对来说比较好
- Aspectj不受类的特殊限制,不管方法是private、或者static、或者final的,都可以代理
- Aspectj不会代理除了限定方法之外任何其他诸如toString(),clone()等方法
Aspectj的使用方法我实在是找不到,等以后找到了再补上吧
注意,像我们下面这种常常在spring中写的aop代码,使用的是jdk代理或者cglib代理,虽然用了Aspectj的注解,但仍然用的是jdk动态代理,或者cglib动态代理。
//声明这是一个组件
@Component
//声明这是一个切面Bean
@Aspect
@Slf4j
public class ServiceAspect { //配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点
@Pointcut("execution(* com.hdj.learn.spring.aop.service..*(..))")
public void aspect() {
} /*
* 配置前置通知,使用在方法aspect()上注册的切入点
* 同时接受JoinPoint切入点对象,可以没有该参数
*/
@Before("aspect()")
public void before(JoinPoint joinPoint) {
log.info("before " + joinPoint);
} //配置后置通知,使用在方法aspect()上注册的切入点
@After("aspect()")
public void after(JoinPoint joinPoint) {
log.info("after " + joinPoint);
} //配置环绕通知,使用在方法aspect()上注册的切入点
@Around("aspect()")
public void around(JoinPoint joinPoint) {
long start = System.currentTimeMillis();
try {
((ProceedingJoinPoint) joinPoint).proceed();
long end = System.currentTimeMillis();
log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");
} catch (Throwable e) {
long end = System.currentTimeMillis();
log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : " + e.getMessage());
}
} //配置后置返回通知,使用在方法aspect()上注册的切入点
@AfterReturning("aspect()")
public void afterReturn(JoinPoint joinPoint) {
log.info("afterReturn " + joinPoint);
} //配置抛出异常后通知,使用在方法aspect()上注册的切入点
@AfterThrowing(pointcut = "aspect()", throwing = "ex")
public void afterThrow(JoinPoint joinPoint, Exception ex) {
log.info("afterThrow " + joinPoint + "\t" + ex.getMessage());
} }
关于怎么获取动态代理生成的class对象的.class文件,参考下面这两篇文章吧:
https://www.cnblogs.com/dengrong/p/10622594.html
http://www.mamicode.com/info-detail-2242036.html
注意看怎么使用 java -classpath sa-jdi.jar "sun.jvm.hotspot.HSDB" 和 jps -l 就行了,其他方法使用了,都没卵用,就HSDB这个东西可以生成class文件
java代理,静态代理、jdk代理、cglib代理、Aspectj的更多相关文章
- Java代理(静态/动态 JDK,cglib)
Java的代理模式是应用非常广泛的设计模式之一,也叫作委托模式,其目的就是为其他的对象提供一个代理以控制对某个对象的访问和使用,代理类负责为委托类预处理消息,过滤消息并转发消息,以及对消息执行后续处理 ...
- 分享知识-快乐自己:三种代理(静态、JDK、CGlib 代理)
1):代理模式(静态代理)点我下载三种模式源码 代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理. 静态代理由 业务实现类.业务代理类 两部分组成 ...
- 《Proxy系列专题》:代理模式(静态、JDK、CGLib)
<Proxy系列专题>:代理模式(静态.JDK.CGLib)使用 现象:在如今互联网时代,项目的复杂度不断的提升,有些场景下需要一定的设计优化来支撑业务的扩展,如为了不改动原始类,但需要对 ...
- 静态代理、动态代理和cglib代理
转:https://www.cnblogs.com/cenyu/p/6289209.html 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处 ...
- 【Java】代理模式,静态代理和动态代理(基于JDK或CGLib)
当我们需要在一个方法之前或之后添加一段逻辑时,自然会想到使用代理类.代理类帮我们代理了实际类的调用,然后可以在实际调用之前和之后添加一些逻辑,从而不浸入实际类. 拓展:由于代理类能在实际类调用之前和之 ...
- Java三种代理模式:静态代理、动态代理和cglib代理
一.代理模式介绍 代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能. 简言之,代理模式就是 ...
- Spring的代理模式(静态,JDK,CGLIB)
一.静态代理 1.定义业务接口 public interface Subject { void doSomeThing(); } 2.真实业务类实现接口 public class RealSu ...
- java 动态代理模式(jdk和cglib)
package proxy.dynamicproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Met ...
- 【java高级编程】JDK和CGLIB动态代理区别
转载:https://blog.csdn.net/yhl_jxy/article/details/80635012 前言 JDK动态代理实现原理(jdk8):https://blog.csdn.net ...
- java设计模式(一)动态代理模式,JDK与CGLIB分析
-本想着这个知识点放到Spring Aop说说可能更合适一点,但因为上一篇有所提到就简单分析下,不足之处请多多评论留言,相互学习,有所提高才是关键! 什么是代理模式: 记得有本24种设计模式的书讲到代 ...
随机推荐
- Java实现 LeetCode 12 整数转罗马数字
12. 整数转罗马数字 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 ...
- Java实现第九届蓝桥杯测试次数
测试次数 题目描述 x星球的居民脾气不太好,但好在他们生气的时候唯一的异常举动是:摔手机. 各大厂商也就纷纷推出各种耐摔型手机.x星球的质监局规定了手机必须经过耐摔测试,并且评定出一个耐摔指数来,之后 ...
- Linux ACL权限查看与设定
getfacl 文件名,可以查看文件的acl权限 setfacl [选项] 文件名,可以设定文件的acl权限,例如:setfacl -m u:boduo:rx /project/ 这时候,创建了bod ...
- hackrf 输出功率测试
使用PortaPack H1的话筒发射功能测试: 144M :8dbm 430M:6dbm 950M:6dbm 1545.42M:0.5dbm 7.42M:18.5dbm 14.2M:16.3dbm
- 【JVM故事】了解JVM的结构,好在面试时吹牛
class文件格式 参考上一篇文章<[JVM故事]一个Java字节码文件的诞生记>,后续还会专门讲解class文件的内部结构. 数据类型 jvm包括两种数据类型,基本类型和引用类型. 基本 ...
- 去摆摊吧,落魄的Java程序员
真的,我也打算去摆摊,宣传语我都想好了.沉默王二,一枚有颜值却靠才华苟且的程序员,<Web 全栈开发进阶之路>作者,CSDN 明星博主,周排名第 4,总排名 40,这数据在众多互联网大咖面 ...
- ubuntu18启动zabbix-agent失败/故障记录
故障现象 ubuntu 16 升级18 之后 安装了zabbix agent 今天突然agent掉了 上去的时候发现 报错: 后来打算-c 启动然后发现 /usr/sbin/zabbix_agentd ...
- Java线程变量问题-ThreadLocal
关于Java线程问题,在博客上看到一篇文章挺好的: https://blog.csdn.net/w172087242/article/details/83375022#23_ThreadLocal_1 ...
- [C#.NET 拾遗补漏]04:你必须知道的反射
阅读本文大概需要 3 分钟. 通常,反射用于动态获取对象的类型.属性和方法等信息.今天带你玩转反射,来汇总一下反射的各种常见操作,捡漏看看有没有你不知道的. 获取类型的成员 Type 类的 GetMe ...
- 【asp.net core 系列】8 实战之 利用 EF Core 完成数据操作层的实现
0. 前言 通过前两篇,我们创建了一个项目,并规定了一个基本的数据层访问接口.这一篇,我们将以EF Core为例演示一下数据层访问接口如何实现,以及实现中需要注意的地方. 1. 添加EF Core 先 ...