• 动态代理实现AOP


    代理

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

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

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

    引入代理的原因:

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

    静态代理

    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
    @Setter
    public 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();
        }
    }
  • 相关阅读:
    模拟光照中的凹凸纹理原理和应用
    Visual Studio 2010 SP1正式开放下载
    同桌的你网工版
    [转载]同桌的你程序员版
    学习计划:SSIS
    基于Java的HTML解析器
    初次使用NHibernate遇到的问题
    .NET下开源CMS系统汇总
    MyEclipse、Tomcat启动项目报错
    VBA 分文件夹 分excel
  • 原文地址:https://www.cnblogs.com/kaituorensheng/p/10704778.html
Copyright © 2020-2023  润新知