靜態代理,動態代理,AOP
阿新 • • 發佈:2022-04-21
靜態代理:
public interface IUser { //儲存使用者 void save(); }
public class IUserImpl implements IUser{ @Override public void save() { System.out.println("模擬儲存使用者"); } }
//靜態代理類,要與目標物件(IUserImpl)實現相同的介面 public class UserProxy implements IUser{ private IUser target = new IUserImpl(); @Overridepublic void save() { System.out.println("代理操作: 開啟事務..."); target.save(); // 執行目標物件的方法 System.out.println("代理操作:提交事務..."); } public static void main(String[] args) { IUser proxy = new UserProxy(); proxy.save(); } }
執行結果:
靜態代理缺點: 如果增加一個方法,除了實現類需要實現這個方法外,所有的代理類也要實現此方法。增加了程式碼的維護成本。那麼要如何解決呢?答案是使用動態代理。
動態代理:
介面:
package com.seeyii.web.yangkun.dynamicProxy;
public interface IVehicle {
void behavior();
}
實現類:
package com.seeyii.web.yangkun.dynamicProxy; /** * @PackageName:com.seeyii.web.yangkun.dynamicProxy * @Description: * @Author 楊坤 * @Date:2022/4/21 14:17 */ public class Car implements IVehicle { @Overridepublic void behavior() { System.out.println("開汽車"); } }
呼叫處理類:
package com.seeyii.web.yangkun.dynamicProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * @PackageName:com.seeyii.web.yangkun.dynamicProxy * @Description: * @Author 楊坤 * @Date:2022/4/21 14:30 */ public class VehicleInvacationHandler<T> implements InvocationHandler { //被代理的物件 private T target; public VehicleInvacationHandler(T target){ this.target=target; } /* * @Author 楊坤 * @Date 14:34 2022/4/21 * proxy 代表動態代理物件 * method 代表正在執行的方法 * args 代表呼叫目標方法時傳入的實參 **/ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("---------before-------"); Object invoke = method.invoke(target, args); System.out.println("---------after-------"); return invoke; } }
啟動類:
package com.seeyii.web.yangkun.dynamicProxy; import java.lang.reflect.Proxy; public class App { public static void main(String[] args) { IVehicle car = new Car(); IVehicle vehicle = (IVehicle)Proxy.newProxyInstance(car.getClass().getClassLoader(), Car.class.getInterfaces(), new VehicleInvacationHandler(car)); vehicle.behavior();
// vehicle.behavior()會呼叫 VehicleInvacationHandler的invoke方法,invoke方法通過反射呼叫被代理類的對應方法
} }
執行結果:
如果被代理的類沒有實現介面,可以用CGLib方式實現動態代理
AOP:
package com.seeyii.web.yangkun.aop; import com.seeyii.web.yangkun.dynamicProxy.Car; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.stereotype.Component; import java.util.Collections; import java.util.List; @Aspect @Component public class AopConfig { @Pointcut("execution( * com.seeyii.web.*.controller..*(..))") public void pointCut() { } @Around("pointCut()") public Object around(ProceedingJoinPoint joinPoin) { System.out.println("前置處理"); Object obj = null; try { //執行目標方法 obj = joinPoin.proceed();
System.out.println("後置處理");
} catch (Throwable throwable) { throwable.printStackTrace(); } return obj; } }