001/* 002 * Copyright 2002-2019 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.aop.support; 018 019import java.io.Serializable; 020import java.util.LinkedHashSet; 021import java.util.Set; 022 023import org.aopalliance.aop.Advice; 024 025import org.springframework.aop.ClassFilter; 026import org.springframework.aop.DynamicIntroductionAdvice; 027import org.springframework.aop.IntroductionAdvisor; 028import org.springframework.aop.IntroductionInfo; 029import org.springframework.core.Ordered; 030import org.springframework.lang.Nullable; 031import org.springframework.util.Assert; 032import org.springframework.util.ClassUtils; 033 034/** 035 * Simple {@link org.springframework.aop.IntroductionAdvisor} implementation 036 * that by default applies to any class. 037 * 038 * @author Rod Johnson 039 * @author Juergen Hoeller 040 * @since 11.11.2003 041 */ 042@SuppressWarnings("serial") 043public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFilter, Ordered, Serializable { 044 045 private final Advice advice; 046 047 private final Set<Class<?>> interfaces = new LinkedHashSet<>(); 048 049 private int order = Ordered.LOWEST_PRECEDENCE; 050 051 052 /** 053 * Create a DefaultIntroductionAdvisor for the given advice. 054 * @param advice the Advice to apply (may implement the 055 * {@link org.springframework.aop.IntroductionInfo} interface) 056 * @see #addInterface 057 */ 058 public DefaultIntroductionAdvisor(Advice advice) { 059 this(advice, (advice instanceof IntroductionInfo ? (IntroductionInfo) advice : null)); 060 } 061 062 /** 063 * Create a DefaultIntroductionAdvisor for the given advice. 064 * @param advice the Advice to apply 065 * @param introductionInfo the IntroductionInfo that describes 066 * the interface to introduce (may be {@code null}) 067 */ 068 public DefaultIntroductionAdvisor(Advice advice, @Nullable IntroductionInfo introductionInfo) { 069 Assert.notNull(advice, "Advice must not be null"); 070 this.advice = advice; 071 if (introductionInfo != null) { 072 Class<?>[] introducedInterfaces = introductionInfo.getInterfaces(); 073 if (introducedInterfaces.length == 0) { 074 throw new IllegalArgumentException("IntroductionAdviceSupport implements no interfaces"); 075 } 076 for (Class<?> ifc : introducedInterfaces) { 077 addInterface(ifc); 078 } 079 } 080 } 081 082 /** 083 * Create a DefaultIntroductionAdvisor for the given advice. 084 * @param advice the Advice to apply 085 * @param ifc the interface to introduce 086 */ 087 public DefaultIntroductionAdvisor(DynamicIntroductionAdvice advice, Class<?> ifc) { 088 Assert.notNull(advice, "Advice must not be null"); 089 this.advice = advice; 090 addInterface(ifc); 091 } 092 093 094 /** 095 * Add the specified interface to the list of interfaces to introduce. 096 * @param ifc the interface to introduce 097 */ 098 public void addInterface(Class<?> ifc) { 099 Assert.notNull(ifc, "Interface must not be null"); 100 if (!ifc.isInterface()) { 101 throw new IllegalArgumentException("Specified class [" + ifc.getName() + "] must be an interface"); 102 } 103 this.interfaces.add(ifc); 104 } 105 106 @Override 107 public Class<?>[] getInterfaces() { 108 return ClassUtils.toClassArray(this.interfaces); 109 } 110 111 @Override 112 public void validateInterfaces() throws IllegalArgumentException { 113 for (Class<?> ifc : this.interfaces) { 114 if (this.advice instanceof DynamicIntroductionAdvice && 115 !((DynamicIntroductionAdvice) this.advice).implementsInterface(ifc)) { 116 throw new IllegalArgumentException("DynamicIntroductionAdvice [" + this.advice + "] " + 117 "does not implement interface [" + ifc.getName() + "] specified for introduction"); 118 } 119 } 120 } 121 122 public void setOrder(int order) { 123 this.order = order; 124 } 125 126 @Override 127 public int getOrder() { 128 return this.order; 129 } 130 131 @Override 132 public Advice getAdvice() { 133 return this.advice; 134 } 135 136 @Override 137 public boolean isPerInstance() { 138 return true; 139 } 140 141 @Override 142 public ClassFilter getClassFilter() { 143 return this; 144 } 145 146 @Override 147 public boolean matches(Class<?> clazz) { 148 return true; 149 } 150 151 152 @Override 153 public boolean equals(@Nullable Object other) { 154 if (this == other) { 155 return true; 156 } 157 if (!(other instanceof DefaultIntroductionAdvisor)) { 158 return false; 159 } 160 DefaultIntroductionAdvisor otherAdvisor = (DefaultIntroductionAdvisor) other; 161 return (this.advice.equals(otherAdvisor.advice) && this.interfaces.equals(otherAdvisor.interfaces)); 162 } 163 164 @Override 165 public int hashCode() { 166 return this.advice.hashCode() * 13 + this.interfaces.hashCode(); 167 } 168 169 @Override 170 public String toString() { 171 return getClass().getName() + ": advice [" + this.advice + "]; interfaces " + 172 ClassUtils.classNamesToString(this.interfaces); 173 } 174 175}