В предыдущей статье мы проанализировали, как прокси -класс генерируется в классе прокси. Мы видели, что кеш -механизм используется внутри прокси. Если класс прокси можно найти в кэше на основе предоставленного загрузчика класса и интерфейса, класс прокси будет возвращен напрямую. В противном случае, ProxyClassFactory Factory будет вызвана для создания класса прокси. Кэш, используемый здесь, представляет собой вторичный кэш, а его клавиша кэша первого уровня генерируется на основе загрузчика класса, а клавиша кэша второго уровня генерируется на основе массива интерфейса. Мы непосредственно опубликуем код, чтобы подробно объяснить конкретный внутренний механизм.
// Ссылка на справочную очередь Private Final ReadingQueue <k> опрокидывание = new Referencequeue <> (); // Базовая реализация кэша, ключ-кэш первого уровня, а значение-кэш второго уровня. Чтобы поддержать NULL, тип ключа MAP установлен для ObjectPrivate Final CONGURRENTMAP <Object, COMPURRENTMAP <объект, поставщик <v >>> map = new Concurrenthashmap <> (); // Обративные записи записи, доступны ли все генераторы класса прокси. Это должно реализовать механизм истечения срока действия кэша частное окончательное окончательное concurrentmap <поставщик <v>, boolean> reversemap = new concurrenthashmap <> (); // завод, который генерирует вторичный ключ кэша, KeyFactoryPrivate Final Bifunction <K, P ,? P, v> valueFactory; // Constructor, завод, который генерирует вторичный ключ кэша, и завод, который генерирует вторичное значение Cache Public SleaseCache (Bifunction <K, P,?> SubkeyFactory, Bifunction <K, P, V> ValueFactory) {this.subkeyFactory = objects.Requirenonnull (subkeyFactory); this.valuefactory = objects.requirenonllull (valueFactory);}Во -первых, давайте посмотрим на переменные члена и конструктор SleedCache. Внутренняя реализация кэша SleaseCache завершается через CONCURRENTMAP. Карта переменной элемента является основной реализацией вторичного кэша. Обратка - это реализация механизма истечения срока действия кэша. Подкифактория - это завод генерации вторичного ключа кеша. Он проходит через конструктор. Стоимость, проходящее здесь, является Keyfactory класса прокси, а ValueFactory - это заводская фабрика вторичного значения кэша. Он проходит через конструктор. Прокси -циксовый класс ProxyClassFactory проходит здесь. Далее давайте посмотрим на метод Get SleedCache.
public v get (k key, parameter) {// Интерфейс, необходимый для реализации здесь, не может быть пустым объектом. // Очистить срок действия кэша ensungestaleentries (); // wroud classloader в Cachekey в качестве ключа для объекта кэша первого уровня cachekey = cachekey.valueof (key, опровержение); // Получить вторичный кэш coundrentMap <объект, поставщик <v >> valuesmap = map.get (cachekey); // Если соответствующее значение не получено на основе ClassLoader if (valuesmap == null) {// Поместите его в CAS, если оно не существует, вставьте его, в противном случае верните исходное значение complorentMap <объект, поставщик <v >> OldValuesMap = map.putifabSent (cachekey, valueMap = new concurrentAshmap <> ()); // Если OldValuesMap имеет значение, это означает, что размещение не удалось, если (OldValuesMap! = Null) {valuesmap = oldValuesMap; }} // Создать ключ кэша второго уровня на основе массива интерфейса, реализованного классом прокси, разделенного на key0, key1, key2, keyx объект subkey = objects.requirenonlull (subkeyfactory.apply (key, parameter)); // Значение вторичного кэша получается через подраздел. Поставщик <v> поставщик = valuemap.get (subkey); Заводская фабрика = null; // Этот цикл обеспечивает механизм опроса. Если условие является ложным, продолжайте повторять еще раз, пока условие не станет истинным, в то время как (true) {// Если значение, полученное через подчинение, не является пустым, если (поставщик! = Null) {// Здесь поставки могут быть заводской или качевиной // Суждение здесь не представлено, но проверяйте в методе получения значения поставщика класса V value = vature = get (););););); if (value! = null) {return value; }} if (factory == null) {// Создание нового заводского экземпляра в качестве соответствующего значения Subkey Factory = New Factory (Key, Parameter, Subkey, Valuesmap); } if (поставщик == null) {// Так что здесь означает, что Subkey не имеет соответствующего значения, поместите заводскую как значение подкауса в поставщике = valuesmap.putifabsent (subkey, factory); if (поставщик == null) {// Так что здесь это означает, что завод успешно размещен в поставщике кэша = Factory; } // В противном случае другие потоки могут изменить значение в течение периода, тогда мы больше не продолжаем присваивать значения подки, но вынимаем их и используем их напрямую} else {// В течение этого периода другие потоки могли изменить значение, поэтому замените исходное значение, если (значения map.replace (подк, поставщик, фабрика)) {// успешно заменить завод на завод по факту. } else {// заменить сбой, продолжить использовать исходное значение поставщика = valuesmap.get (subkey); }}}}Метод Get SleadCache не синхронизируется с замками, так как он достигает безопасности потока? Поскольку все его модифицированные переменные-члены используют concurrentMap, этот класс безопасен для потока. Следовательно, он делегирует свою собственную безопасность потока в одновременную карту, а метод GET уменьшает максимально возможные блоки кода синхронизации, что может эффективно повысить производительность SleadCache. Мы видим, что ClassLoader - это ключ из кэша уровня 1, так что мы можем отфильтровать его сначала в соответствии с ClassLoader, потому что классы, загруженные различными загрузчиками класса, разные. Затем он использует интерфейсную массив для генерации ключа вторичного кеша. Здесь есть некоторые оптимизации. Поскольку большинство классов реализуют один или два интерфейса, клавиша вторичного кэша делится на key0, key1, key2 и keyx. Key0 к Key2 означает, что от 0 до 2 интерфейсов реализованы, и KeyX означает, что 3 или более интерфейсов реализованы. На самом деле, большинство из них будут использовать только Key1 и Key2. Генеральная фабрика этих ключей находится в классе прокси, и ключевая фабрика проходит через конструктор SleadCache. Значение кеша второго уровня здесь-это заводский экземпляр, а конечное значение класса прокси-класса получается через заводскую фабрику.
Заводской заводской фабрики финального класса реализует поставщик <v> {// Клавиша кэша уровня 1, генерируйте частный конечный K -ключ в соответствии с ClassLoader; // интерфейс массив частный окончательный параметр p, реализованный классом прокси; // клавиша кэша уровня 2, генерируйте частное окончательное подразделение объекта в соответствии с интерфейсным массивом; // Уровень 2 кэш private final complorentMap <объект, поставщик <v >> valuesmap; Factory (k Key, PARATER, UBER SOPKEY, CONCURRENTMAP <объект, поставщик <v >> ValuesMap) {this.key = key; this.parameter = параметр; this.subkey = subkey; this.valuesmap = valuesmap; } @Override public synchronized v get () {// Здесь я снова перехожу во вторичный кэш, чтобы заставить поставщика проверить, является ли он самим заводским поставщиком <v> поставщик = valuesmap.get (subkey); if (Поставщик! = Это) {// Здесь я проверяю, является ли поставщик самим заводским экземпляром, если нет, вернуть ноль и позвольте вызывающему абоненту продолжать опросить и повторить // в течение периода, поставщик может быть заменен на класс CacheValue, или он удален из вторичного кэша из -за неспособности создать класс прокси; } V value = null; try {// делегируйте ValueFactory для генерации класса прокси, здесь значение класса прокси будет генерировано через входящий ProxyClassFactory = objects.Requirenonlull (valueFactory.Apply (ключ, параметр)); } наконец {// Если генерация класса прокси не удается, удалите этот вторичный кэш if (value == null) {valuesmap.remove (subkey, this); }} // Только значение значения не пустое, может ли оно достичь здесь. Значение! = Null; // CACHEVALUE CACHEVALUE <V> CACHEVALUE = NEW CACHEVALUE <> (значение); // Поместите упакованный CacheValue в вторичный кэш. Эта операция должна быть успешной, в противном случае будет сообщена ошибка, если (valuesmap.replace (subkey, this, cachevalue)) {// после успешного поместить Cachevalue во вторичный кэш, отметьте его reversemap.put (cachevalue, boolean.true); } else {бросить новый AssertionError ("не должен быть здесь"); } // Наконец -то возвращает возвращаемое значение класса прокси, которое не обернуто слабой ссылкой; }}Давайте снова посмотрим на фабрику внутреннего завода класса, и мы видим, что его метод получения синхронизируется с использованием синхронизированного ключевого слова. После выполнения метода GET сначала убедитесь, является ли поставщик, соответствующий подки, самой фабрикой. Если нет, то это вернет NULL, и метод Get SleadCache продолжит повторять попытку. Если это действительно сама фабрика, то ProxyClassFactory будет делегирован для генерации класса прокси, который передается при построении SLEADCACHE. Итак, здесь объясняется, почему проксикассфакторная внутренняя фабрика в прокси призвана для создания класса прокси в конце. После генерации класса прокси, он использует слабую ссылку, чтобы обернуть его и поместить его в реверсии, и, наконец, возвращает исходный класс прокси.
До сих пор мы подробно обнаружили реализацию кэша SleasdCache, включая его принципы реализации кэша второго уровня и принципы реализации кэша второго уровня, а также принцип генерации ключа кэша второго уровня и того, как он вызывает ProxyClassFactory для создания класса Proxy в конце. В следующей статье мы перейдем в класс проксигенератора, чтобы увидеть процесс генерации байт -кодов конкретного класса прокси.
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.