предисловие
Эта статьяspi
Четвертая частьspi
увеличился вAOP
, или то же самое, что и предыдущий, давайте сначала введем АОП из знакомого спринга.
AOP
Это общая тема, и идеи не могут быть достигнуты в одночасье.Например, архитектурный дизайн начинается сAll in One
прибытьSOA
Это также постепенный процесс эволюции, поэтому в этой статье также говорится о процессе идеологической эволюции этого АОП.
Вопросы для интервью в прямом эфире
- Вы упомянули, что spi в даббо тоже увеличился
AOP
, тогда скажите мне, какой шаблон проектирования используется и как это делает dubbo.
Сразу к делу
если мы возьмемAOP
самые распространенные сценарии事务
Итак, каков был наш первоначальный подход?
Простой способ
public class EmployeeServiceImpl implements IEmployeeService {
private TransactionManager txManager;
@Override
public void save() {
try {
txManager.begin();
System.out.println("保存操作");
txManager.commit();
}catch (Exception e){
txManager.rollback();
e.printStackTrace();
}
}
@Override
public void update() {
try {
txManager.begin();
System.out.println("更新操作");
txManager.commit();
}catch (Exception e){
txManager.rollback();
e.printStackTrace();
}
}
}
Проблемы с этими кодами очевидны, например
- Много дублирования кода для обработки транзакций
- Согласно идее разделения ответственности, в бизнес-методах нужно обрабатывать только бизнес-функции, а транзакции не обрабатывать.
Первое, о чем мы думаем для оптимизации кода, это шаблон проектирования, затем мы вводим следующую оптимизацию.
декоративный узор
public class APP {
@Test
public void testSave() throws Exception {
IEmployeeService service = new EmployeeServiceImplWapper(new TransactionManager(),
new EmployeeServiceImpl());
service.save();
}
@Test
public void testUpdate() throws Exception {
IEmployeeService service = new EmployeeServiceImplWapper(new TransactionManager(),
new EmployeeServiceImpl());
service.update();
}
}
Украшая шаблон проектирования, мы решаем две проблемы, с которыми столкнулись выше, но также вносим новые проблемы, на стороне клиента мы выставляем реальный объектEmployeeServiceImpl
, это очень небезопасно, так можем ли мы скрыть настоящий объект, чтобы пользователь его не видел?
статический прокси
Таким образом, реальный объект в определенной степени скрыт от пользователя, но это также приводит к новым проблемам.
- Если методов, которые необходимо проксировать, много, то каждый из них должен быть обработан, например, обрабатывается только фигура.
save
метод, в случае, если методов много, его нужно обрабатывать много раз - После того, как интерфейс добавляет метод, помимо того, что все реализующие классы должны реализовать этот метод, все прокси-классы также должны реализовать этот метод (
EmployeeServiceImpl
а такжеEmployeeServiceImplProxy
должны быть изменены), что увеличивает сложность обслуживания кода - Интерфейс прокси-объекта обслуживает только определенный тип объекта, например
EmployeeServiceImplProxy
только дляIEmployeeService
Сервис интерфейса, если я добавлю новыйIRoleService
, сделать другоеRoleServiceImplProxy
, увеличивая сложность обслуживания
Ввиду поставленных выше вопросов, можем ли мы его оптимизировать? Ответ - да
Динамический прокси
Динамический прокси-класс динамически генерируется JVM посредством отражения и других механизмов во время работы программы, поэтому файл байт-кода прокси-класса отсутствует Отношение между прокси-объектом и реальным объектом определяется во время работы программы. .
Мы уже говорили о способах и отличиях динамического прокси, вот краткая демонстрация динамического прокси jdk.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class JDKProxyTest {
@Autowired
private TransactionManagerInvocationHandle handle;
@Test
public void testSave() throws Exception {
IEmployeeService service = handle.getProxyObject();
service.save();
}
@Test
public void testUpdate() throws Exception {
IEmployeeService service = handle.getProxyObject();
service.update();
}
}
public class TransactionManagerInvocationHandle implements InvocationHandler {
@Setter
private TransactionManager txManager;
@Setter
private Object target;//真实对象
//生成代理对象
//泛型只是为了调用时不用强转,如果用Object的话调用时需要强转
public <T> T getProxyObject() {
return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(),//类加载器
target.getClass().getInterfaces(),//为哪些接口做代理(拦截什么方法)
this);//为哪个类监听增强操作的方法(把这些方法拦截到哪里处理)
}
//如何做增强操作(被拦截的方法在这里增强处理)
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object obj = null;
try {
txManager.begin();
//原封不动调用之前的方法
obj = method.invoke(target, args);
txManager.commit();
return obj;
} catch (Exception e) {
e.printStackTrace();
txManager.rollback();
}
return obj;
}
}
Таким образом, пользователю не нужно заботиться о логике транзакции.getProxyObject
Все еще слишком сложно получить динамический прокси-объект, так как я могу не вызыватьgetProxyObject
Как насчет скрытого внедрения динамических прокси-объектов?Анализ исходного кода Dubbo — простой принцип, интеграция с Spring
dubbo-spi-aop
После просмотра стольких эволюций вы до сих пор этого не видите?dubbo
Тень исходного кода?dubbo
делаетspi
При проектировании тоже идет процесс эволюции и оптимизации.Посмотрим как это делает dubbo
//dubbo spi中的aop
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
Приводятся следующие документы
Когда ExtensionLoader загружает точку расширения, если загруженная точка расширения имеет конструктор копирования, он определяется как класс-оболочка точки расширения.
Содержимое класса-оболочки:
package com.alibaba.xxx;
import com.alibaba.dubbo.rpc.Protocol;
public class XxxProtocolWrapper implemenets Protocol {
Protocol impl;
public XxxProtocol(Protocol protocol) { impl = protocol; }
// 接口方法做一个操作后,再调用extension的方法
public void refer() {
//... 一些操作
impl.refer();
// ... 一些操作
}
// ...
}
Класс Wrapper может переместить всю общую логику точки расширения в Wrapper. Недавно добавленный Wrapper добавляет логику ко всем точкам расширения, что чем-то похоже на АОП, то есть Wrapper проксирует точки расширения.
Вы можете найти его здесь, в даббоspi
Повысилсяaop
, на самом деле является шаблоном проектирования декоратора. Но из приведенной выше эволюции мы обнаружили, что шаблон проектирования декоратора по-прежнему имеет много недостатков, за которыми следует постепенная эволюция и, наконец, динамический прокси. Как dubbo справляется с этим недостатком и постепенно развивается?
В даббо есть понятие扩展点自适应
, то есть внедрение точки расширения в интерфейсAdaptive
instance, пока не будет выполнен метод, реализация которого вызывается точкой расширения, об этом будет рассказано в следующей статье.Adaptive
Он будет представлен подробно, эта статья на самом деле является просветительской статьей следующей.
Стучите по доске, чтобы нарисовать ключевые моменты — советы
Поскольку в этой статье упоминается aop Spring, вот небольшая хитрость, SpringAOP
Всего существует 5 методов улучшения, а именно:
Расширенный тип | Сценарии применения |
---|---|
предварительное усиление | Контроль разрешений, запись журнала вызовов |
задний наддув | Данные результатов статистического анализа |
аномальное усиление | Информация об исключении метода регистрации |
окончательное улучшение | освободить ресурсы |
Улучшение объемного звучания | Кэш, производительность, разрешения, управление транзакциями |
На собеседовании я тоже спрашивал про 5 методов улучшения, но многие студенты говорили, что я каждый день работаю сверхурочно, и мне некогда их запоминать.Но на самом деле, если понять его дизайнерские идеи, то можно "постичь память" , Если вы хотите забыть это позже, вы не можете забыть это.
//环绕
try {
//前置
System.out.println("=====");
//后置
}catch (Exception e){
//异常
}finally {
//最终
}
На самом деле, его пять способов основаны наtry-catch-finally
Пока вы помните идею этого дизайна, вы, естественно, не забудете эти 5 способов.Это то, что я неоднократно подчеркивал ранее.Если вы понимаете принципы и идеи дизайна, многие вещи все-в-одном.
напиши в конце
Feichao — это технический публичный аккаунт, в котором основное внимание уделяется принципам, исходному коду и навыкам разработки, оригинальному тематическому анализу исходного кода в аккаунте и реальному сражению принципов исходного кода в реальных сценах (ключевые моменты).Отсканируйте QR-код нижеОбратите внимание на Фей Чао, пусть те, кто должен строить ракеты, перестанут трахаться!