Реализация АОП с помощью Proxy.newProxyInstance

задняя часть Шаблоны проектирования

Введение в метод newProxyInstance()

Метод newInstance() класса Proxy имеет три параметра:

Загрузчик ClassLoader:
Это тип загрузчика классов, вам не нужно обращать на него внимание, вам просто нужно знать, как его получить: MyInterface.class.getClassLoader() может получить объект ClassLoader, да, если у вас есть класс объект Получить объект ClassLoader;
Интерфейсы класса []:
Укажите, какие интерфейсы должны быть реализованы объектом, возвращаемым методом newProxyInstance(). Да, вы можете указать несколько интерфейсов. Например, в приведенном выше примере мы указали только один интерфейс: Class[] cs = {MyInterface.class} ;
Обработчик вызова h:
Это самый важный параметр! Это интерфейс! Его зовут обработчик вызовов! Независимо от того, какой метод вы вызываете для прокси-объекта, он вызывает метод invoke() InvocationHandler!

Введение в АОП

Аспектно-ориентированное программирование (АОП) — горячая тема. АОП, что в Китае примерно переводится как «аспектно-ориентированное программирование».

  • «Аспектно-ориентированное программирование», такое название не очень легко понять и может ввести в заблуждение.
  • Автор не раз слышал речи типа "ООП/ООД11 вот-вот устареет, АОП - метод разработки ПО нового поколения". В АОП значение аспекта может быть более подходящим для понимания как «аспект». Поэтому автор предпочитает перевод «аспектно-ориентированное программирование». Технология, которая динамически и единообразно добавляет функции в программу без изменения исходного кода, может быть достигнута с помощью динамических агентов предварительной компиляции и времени выполнения.
  • АОП на самом деле является продолжением шаблона проектирования GoF. Шаблон проектирования неустанно преследует развязку между вызывающей и вызываемой сторонами и повышает гибкость и масштабируемость кода. Можно сказать, что АОП является реализацией этой цели.
    Объекты приложения делают только то, что должны делать — завершают бизнес-логику — и ничего больше. Они не несут ответственности (и даже не осведомлены) о других проблемах системного уровня, таких как ведение журнала или поддержка транзакций.

Основная функция АОП

Ведение журнала, статистика производительности, контроль безопасности, обработка транзакций, обработка исключений и т. д. wn и расширения

Основная цель АОП

Отделить от кода бизнес-логики код ведения журнала, статистики производительности, контроля безопасности, обработки транзакций, обработки исключений и т. д. Разделив эти поведения, мы надеемся, что сможем разделить их на методы, которые не управляют бизнес-логикой, а затем изменить этот код, который не влияет на бизнес-логику, когда он ведет себя.

Реализация АОП

package org.java.base.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MainApp1 {
 public static void main(String[] args) {
 ClassLoader loader = MainApp1.class.getClassLoader();
 Class[] cs = {Waiter.class};
 Waiter target = new MyWaiter();
 MyInvocationHandler h = new MyInvocationHandler(target);
 Waiter waiter = (Waiter)Proxy.newProxyInstance(loader, cs, h);
 waiter.serve();
 }
}
class MyInvocationHandler implements InvocationHandler {
 public Waiter target;
 public MyInvocationHandler(Waiter 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;
 }
}
package org.java.base.proxy;
/**
 * 后置增强
 * @author Liuhaihua
 *
 */
public interface AfterAdvice {
 public void after();
}
package org.java.base.proxy;
/**
 * 前置增强
 * @author Liuhaihua
 *
 */
public interface BeforeAdvice {
 public void before();
}

package org.java.base.proxy;
public class MyWaiter implements Waiter {
 public void serve() {
 System.out.println("服务...");
 }
}
package org.java.base.proxy;
public interface Waiter {
 // 服务
 public void serve();
 }
 package org.java.base.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 它用来生成代理对象
 * 它需要所有的参数
 * * 目标对象
 * * 增强
 * @author cxf
 */
/**
 * 1. 创建代理工厂
 * 2. 给工厂设置三样东西:
 * * 目标对象:setTargetObject(xxx);
 * * 前置增强:setBeforeAdvice(该接口的实现)
 * * 后置增强:setAfterAdvice(该接口的实现)
 * 3. 调用createProxy()得到代理对象
 * * 执行代理对象方法时:
 * > 执行BeforeAdvice的before()
 * > 目标对象的目标方法
 * > 执行AfterAdvice的after()
 * @author cxf
 *
 */
public class ProxyFactory {
 private Object targetObject;//目标对象
 private BeforeAdvice beforeAdvice;//前置增强
 private AfterAdvice afterAdvice;//后置增强
 /**
 * 用来生成代理对象
 * @return
 */
 public Object createProxy() {
 /*
 * 1. 给出三大参数
 */
 ClassLoader loader = this.getClass().getClassLoader();
 Class[] interfaces = targetObject.getClass().getInterfaces();
 InvocationHandler h = new InvocationHandler() {
 public Object invoke(Object proxy, Method method, Object[] args)
 throws Throwable {
 /*
 * 在调用代理对象的方法时会执行这里的内容
 */
 // 执行前置增强
 if(beforeAdvice != null) {
 beforeAdvice.before();
 }
 
 Object result = method.invoke(targetObject, args);//执行目标对象的目标方法
 // 执行后置增强
 if(afterAdvice != null) {
 afterAdvice.after();
 }
 
 // 返回目标对象的返回值
 return result;
 }
 };
 /*
 * 2. 得到代理对象
 */
 Object proxyObject = Proxy.newProxyInstance(loader, interfaces, h);
 return proxyObject;
 }
 
 
 public Object getTargetObject() {
 return targetObject;
 }
 public void setTargetObject(Object targetObject) {
 this.targetObject = targetObject;
 }
 public BeforeAdvice getBeforeAdvice() {
 return beforeAdvice;
 }
 public void setBeforeAdvice(BeforeAdvice beforeAdvice) {
 this.beforeAdvice = beforeAdvice;
 }
 public AfterAdvice getAfterAdvice() {
 return afterAdvice;
 }
 public void setAfterAdvice(AfterAdvice afterAdvice) {
 this.afterAdvice = afterAdvice;
 }
}


Загрузка кода:git ee.com/go on ah plug ah/max…