动态代理实现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();
    }
}

复制代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 以下是 JDK 动态代理实现 AOP 的步骤: 1. 创建一个接口,定义需要进行 AOP 的方法。 2. 创建一个代理类,实现 InvocationHandler 接口,并重写 invoke 方法。 3. 在 invoke 方法中,根据需要进行 AOP 增强处理,例如在方法前后添加日志、事务等等。 4. 使用 Proxy 类的 newProxyInstance 方法创建代理对象。 5. 将代理对象转换为接口类型,并调用接口方法,代理类中的 invoke 方法会被调用,从而实现 AOP 增强处理。 下面是一个简单的例子,演示如何使用 JDK 动态代理实现 AOP: ```java // 定义接口 public interface UserService { void addUser(String name); } // 实现接口 public class UserServiceImpl implements UserService { public void addUser(String name) { System.out.println("添加用户:" + name); } } // 代理类 public class UserServiceProxy implements InvocationHandler { private Object target; public UserServiceProxy(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("开始事务"); Object result = method.invoke(target, args); System.out.println("提交事务"); return result; } } // 使用代理类 public class Main { public static void main(String[] args) { UserService userService = new UserServiceImpl(); UserService proxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), new UserServiceProxy(userService)); proxy.addUser("张三"); } } ``` 运行结果: ``` 开始事务 添加用户:张三 提交事务 ``` ### 回答2: JDK动态代理是一种实现AOP(面向切面编程)的方式。AOP主要是通过在程序运行期间动态地将额外的逻辑注入到目标对象的方法中,从而实现横切关注点的分离和复用。JDK动态代理是Java语言提供的一种代理方式,基于接口实现动态代理,以下是其实现AOP的步骤: 1. 定义切面类:切面是横切关注点的实现,一般包括需解决的问题和实现逻辑。切面类通常实现了InvocationHandler接口。 2. 创建目标对象:创建需要被代理的目标对象,并且实现了接口。 3. 获取代理对象:通过Proxy类中的newProxyInstance()方法获取代理对象。该方法接收三个参数,分别是目标对象的ClassLoader、目标对象的所有接口以及切面对象。 4. 调用代理对象方法:通过代理对象调用方法时,会自动触发InvocationHandler中的invoke()方法。 5. 在invoke()方法中实现逻辑:在invoke()方法中,我们可以根据需要进行一些额外的逻辑操作,如在目标方法之前或之后进行一些其他操作。 通过以上步骤,JDK动态代理可以在运行时为目标对象的方法添加额外的逻辑实现,达到AOP的目的。这种方式的优点是实现简单,无需引入额外的依赖库,且支持接口代理;但缺点是只能通过接口进行代理,无法对类进行直接代理。 ### 回答3: JDK动态代理是一种实现面向切面编程(AOP)的方式之一。以下是JDK动态代理实现AOP的步骤: 1. 定义切面类:首先,我们需要定义一个切面类,该类包含了我们要在目标对象的方法之前或之后执行的代码。切面类需要实现InvocationHandler接口。 2. 创建目标对象:接下来,我们需要创建一个目标对象,即我们要在其方法上实施切面的对象。 3. 创建代理对象:使用Proxy类的静态newProxyInstance方法创建一个代理对象。该方法接受三个参数:ClassLoader对象、目标对象的接口数组以及InvocationHandler对象。ClassLoader负责加载代理对象,目标对象的接口数组指定了代理对象需要实现的接口,InvocationHandler对象执行切面逻辑。 4. 调用方法:通过代理对象调用目标对象的方法,代理对象会在方法执行前后执行切面逻辑。 5. 前置通知:在切面类的invoke方法中,我们可以通过method.invoke(target, args)调用目标对象的方法,同时可以在此之前执行我们定义的前置通知。 6. 后置通知:在切面类的invoke方法中,我们同样可以通过method.invoke(target, args)调用目标对象的方法,同时可以在此之后执行我们定义的后置通知。 总结:JDK动态代理实现AOP的步骤包括定义切面类、创建目标对象、创建代理对象,调用方法以及前置和后置通知的执行。使用代理对象调用目标对象的方法时,会自动执行所定义的切面逻辑,从而实现AOP的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值