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.util.Assert; 031import org.springframework.util.ClassUtils; 032 033/** 034 * Simple {@link org.springframework.aop.IntroductionAdvisor} implementation 035 * that by default applies to any class. 036 * 037 * @author Rod Johnson 038 * @author Juergen Hoeller 039 * @since 11.11.2003 040 */ 041@SuppressWarnings("serial") 042public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFilter, Ordered, Serializable { 043 044 private final Advice advice; 045 046 private final Set<Class<?>> interfaces = new LinkedHashSet<Class<?>>(); 047 048 private int order = Ordered.LOWEST_PRECEDENCE; 049 050 051 /** 052 * Create a DefaultIntroductionAdvisor for the given advice. 053 * @param advice the Advice to apply (may implement the 054 * {@link org.springframework.aop.IntroductionInfo} interface) 055 * @see #addInterface 056 */ 057 public DefaultIntroductionAdvisor(Advice advice) { 058 this(advice, (advice instanceof IntroductionInfo ? (IntroductionInfo) advice : null)); 059 } 060 061 /** 062 * Create a DefaultIntroductionAdvisor for the given advice. 063 * @param advice the Advice to apply 064 * @param introductionInfo the IntroductionInfo that describes 065 * the interface to introduce (may be {@code null}) 066 */ 067 public DefaultIntroductionAdvisor(Advice advice, IntroductionInfo introductionInfo) { 068 Assert.notNull(advice, "Advice must not be null"); 069 this.advice = advice; 070 if (introductionInfo != null) { 071 Class<?>[] introducedInterfaces = introductionInfo.getInterfaces(); 072 if (introducedInterfaces.length == 0) { 073 throw new IllegalArgumentException("IntroductionAdviceSupport implements no interfaces"); 074 } 075 for (Class<?> ifc : introducedInterfaces) { 076 addInterface(ifc); 077 } 078 } 079 } 080 081 /** 082 * Create a DefaultIntroductionAdvisor for the given advice. 083 * @param advice the Advice to apply 084 * @param ifc the interface to introduce 085 */ 086 public DefaultIntroductionAdvisor(DynamicIntroductionAdvice advice, Class<?> ifc) { 087 Assert.notNull(advice, "Advice must not be null"); 088 this.advice = advice; 089 addInterface(ifc); 090 } 091 092 093 /** 094 * Add the specified interface to the list of interfaces to introduce. 095 * @param ifc the interface to introduce 096 */ 097 public void addInterface(Class<?> ifc) { 098 Assert.notNull(ifc, "Interface must not be null"); 099 if (!ifc.isInterface()) { 100 throw new IllegalArgumentException("Specified class [" + ifc.getName() + "] must be an interface"); 101 } 102 this.interfaces.add(ifc); 103 } 104 105 @Override 106 public Class<?>[] getInterfaces() { 107 return ClassUtils.toClassArray(this.interfaces); 108 } 109 110 @Override 111 public void validateInterfaces() throws IllegalArgumentException { 112 for (Class<?> ifc : this.interfaces) { 113 if (this.advice instanceof DynamicIntroductionAdvice && 114 !((DynamicIntroductionAdvice) this.advice).implementsInterface(ifc)) { 115 throw new IllegalArgumentException("DynamicIntroductionAdvice [" + this.advice + "] " + 116 "does not implement interface [" + ifc.getName() + "] specified for introduction"); 117 } 118 } 119 } 120 121 public void setOrder(int order) { 122 this.order = order; 123 } 124 125 @Override 126 public int getOrder() { 127 return this.order; 128 } 129 130 @Override 131 public Advice getAdvice() { 132 return this.advice; 133 } 134 135 @Override 136 public boolean isPerInstance() { 137 return true; 138 } 139 140 @Override 141 public ClassFilter getClassFilter() { 142 return this; 143 } 144 145 @Override 146 public boolean matches(Class<?> clazz) { 147 return true; 148 } 149 150 151 @Override 152 public boolean equals(Object other) { 153 if (this == other) { 154 return true; 155 } 156 if (!(other instanceof DefaultIntroductionAdvisor)) { 157 return false; 158 } 159 DefaultIntroductionAdvisor otherAdvisor = (DefaultIntroductionAdvisor) other; 160 return (this.advice.equals(otherAdvisor.advice) && this.interfaces.equals(otherAdvisor.interfaces)); 161 } 162 163 @Override 164 public int hashCode() { 165 return this.advice.hashCode() * 13 + this.interfaces.hashCode(); 166 } 167 168 @Override 169 public String toString() { 170 return ClassUtils.getShortName(getClass()) + ": advice [" + this.advice + "]; interfaces " + 171 ClassUtils.classNamesToString(this.interfaces); 172 } 173 174}