时间: 2020-09-3|83次围观|0 条评论


代理

代理顾名思义:代为处理。不是对目标对象的直接操作,而是通过代理对目标对象进行包装,此时可以在目标对象的基础上添加额外的操作以满足业务需求。图示

动态代理实现AOP插图

分类:动态代理、静态代理。

代理三要素:共同接口、真实对象、代理对象

动态代理实现AOP插图1

引入代理的原因:

在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用【解耦】。 

静态代理

public interface Action {    public void doSomething();}public class Proxyc implements Action{    Action realObject;    public Proxyc(Action action) {        realObject = action;    }    @Override    public void doSomething() {        System.out.println("被拦截前...");        realObject.doSomething();        System.out.println("被拦截后...");    }    public static void main(String[] args) {        Proxyc proxy = new Proxyc(new RealObject());        proxy.doSomething();    }}

优点:扩展原功能,不侵入代码

缺点:假如有10个不同的实际对象,对应10个不同的方法,该如何写呢?

1) 要么创建不同的代理类,代理后这样:

proxy.doSomething()proxy2.doSomething2()proxy3.doSomething3()...

问题:创建多个功能类似的代理类,仅传入的真实对象不同

2) 要么创建一个代理,实现不同的接口:

proxy.doSomething()proxy.doSomething2()proxy.doSomething3()...

问题:代理类不断膨胀

动态代理

代理由静态转为静态源于静态代理引入的额外工作。

动态代理就是我们上面提到的方案一,只不过这些proxy的创建都是自动的并且是在运行期生成的。

很多繁琐的编程可以用动态代理解决

实现方式

  • 反射(依赖接口)
    •   优点:最小化依赖关系;平滑jdk升级;代码简单
  • cglib等(依赖子类)
    •   优点:不限制实现接口;只操作关心的类;高性能

反射方式举例

public interface Action {    public void doSomething();}public class RealObject implements Action{    @Override    public void doSomething() {        System.out.println("I'm RealObject~");    }}public class DynamicProxyHandler implements InvocationHandler {    private Object realObject;    public DynamicProxyHandler(Object realObject) {        this.realObject = realObject;    }    @Override    public Object invoke(Object object, Method method, Object[] args) {        Object result = null;        try {            result = method.invoke(realObject, args);        } catch (InvocationTargetException|IllegalAccessException e) {            e.printStackTrace();        }        return result;    }    public static void main(String[] args) {        RealObject realObject = new RealObject();        Action action = (Action) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Action.class},                new DynamicProxyHandler(realObject));        action.doSomething();    }}

通过Proxy.newProxyInstance()生成代理对象,需要传入3个参数:classLoader + 代理接口 + InvocationHandler实例,

其中InvocationHandler接口,该接口定义了一个invoke方法,proxy最是最终生成的一个代理实例,一般不会用到,参数method是被代理目标实例的某个具体的方法,通过它可以发起目标实例方法的反射调用;参数args是通过被代理实例某一个方法的入参,在方法反射调用时候使用,通过代理将横切逻辑代码和业务类的代码编织到了一起。

动态代理的应用场景

日志

监控

鉴权

......

AOP

切面编程,是对OOP(面向对象编程)的一种补充,解决OOP其对对于跨越不同类、对象,纠缠逻辑变现的不足

AOP实例1

public interface Waiter {    public void service();}public class ManWaiter implements Waiter{    @Override    public void service() {        System.out.println("service...");    }}

 

public interface BeforeAdvice {    public void before();}public interface AfterAdvice {    public void after();}

 

@Getter@Setterpublic class ProxyFactory {    Object target;    BeforeAdvice beforeAdvice;    AfterAdvice afterAdvice;    public Object createProxy() {        ClassLoader classLoader = this.getClass().getClassLoader();        Class[] interfaces = target.getClass().getInterfaces();        InvocationHandler invocationHandler = new InvocationHandler() {            @Override            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                if (beforeAdvice != null) {                    beforeAdvice.before();                }                Object result = method.invoke(target, args);                afterAdvice.after();                return result;            }        };        Object proxyObject = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);        return proxyObject;    }    public static void main(String[] args) {        ProxyFactory proxyFactory = new ProxyFactory();        proxyFactory.setTarget(new ManWaiter());        proxyFactory.setBeforeAdvice(new BeforeAdvice() {            @Override            public void before() {                System.out.println("Before Service.");            }        });        proxyFactory.setAfterAdvice(new AfterAdvice() {            @Override            public void after() {                System.out.println("After Service.........");            }        });        Waiter waiter = (Waiter)proxyFactory.createProxy();        waiter.service();    }}

 

AOP实例2

public interface UserService {    public void service();}public class UserServiceImpl implements UserService{    @Override    public void service() {        System.out.println("In Service.......");        try {            Thread.sleep(2000);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("Service end.");    }}

 

public class MethodPerformance {    private long start;    private long end;    String serviceMethod;    public MethodPerformance(String serviceMethod) {        this.serviceMethod = serviceMethod;        start = System.currentTimeMillis();    }    public void printPerformance() {        end = System.currentTimeMillis();        System.out.println(serviceMethod + " cost Time: " + (end - start));    }}public class PerformanceMonitor {    public static ThreadLocal<MethodPerformance> performanceThreadLocal = new ThreadLocal<>();    public static void begin(String method) {        System.out.println("Start monitor>>");        MethodPerformance methodPerformance = new MethodPerformance(method);        performanceThreadLocal.set(methodPerformance);    }    public static void end() {        System.out.println("End monitor.");        performanceThreadLocal.get().printPerformance();    }}

 

public class PerformanceHandler implements InvocationHandler {    Object target;    public PerformanceHandler(Object object) {        target = object;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) {        Object result = null;        try {            PerformanceMonitor.begin(target.getClass().getName() + ":" + method.getName());            result = method.invoke(target, args);            PerformanceMonitor.end();        } catch (IllegalAccessException| InvocationTargetException e) {            e.printStackTrace();        }        return result;    }    public static void main(String[] args) {        UserService userService = new UserServiceImpl();        ClassLoader classLoader = userService.getClass().getClassLoader();        Class[] interfaces = userService.getClass().getInterfaces();        InvocationHandler invocationHandler = new PerformanceHandler(userService);        UserService obj = (UserService) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);        obj.service();    }}

 

文章转载于:https://www.cnblogs.com/kaituorensheng/p/10704778.html

原著是一个有趣的人,若有侵权,请通知删除

本博客所有文章如无特别注明均为原创。
复制或转载请以超链接形式注明转自起风了,原文地址《动态代理实现AOP
   

还没有人抢沙发呢~