项目地址
项目地址:https://toscode.gitee.com/nepxion/Matrix
原理分析
Spring AutoProxy机制
它统一封装接口(Spring)代理和类代理(CGLIB),注解无论在接口和类的头部或者方法上,都可以让业务端执行有效切面,可以轻松快速实现对接口或者类的复杂代理业务
DefaultAutoScanProxy
,继承DefaultAutoScanProxy
,定义包扫描路径,代理模式和扫描模式;指定拦截器和注解。
@Component("myAutoScanProxyForClass")
public class MyAutoScanProxyForClass extends DefaultAutoScanProxy {
private static final long serialVersionUID = -5968030133395182024L;
// 多个包路径,用“;”分隔
private static final String SCAN_PACKAGES = "com.charles";
@SuppressWarnings("rawtypes")
private Class[] commonInterceptorClasses;
@SuppressWarnings("rawtypes")
private Class[] classAnnotations;
public MyAutoScanProxyForClass() {
super(SCAN_PACKAGES, ProxyMode.BY_CLASS_ANNOTATION_ONLY, ScanMode.FOR_CLASS_ANNOTATION_ONLY);
}
@SuppressWarnings("unchecked")
@Override
protected Class<? extends MethodInterceptor>[] getCommonInterceptors() {
if (commonInterceptorClasses == null) {
commonInterceptorClasses = new Class[]{MyInterceptor1.class};
}
return commonInterceptorClasses;
}
@SuppressWarnings("unchecked")
@Override
protected Class<? extends Annotation>[] getClassAnnotations() {
if (classAnnotations == null) {
classAnnotations = new Class[]{Annotation1.class};
}
return classAnnotations;
}
@Override
protected void classAnnotationScanned(Class<?> targetClass, Class<? extends Annotation> classAnnotation) {
System.out.println("Class annotation scanned, targetClass=" + targetClass + ", classAnnotation=" + classAnnotation);
}
}
AbstractAutoProxyCreator#postProcessAfterInitialization
,入口类在AbstractAutoProxyCreator
。判断类是否被拦截,如果被拦截,获取被拦截后的代理类。
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
Aspect
获取拦截器是用的AbstractAdvisorAutoProxyCreator
,而Nepxion Matrix
实现的子类是是AbstractAutoScanProxy
,那么分析一下AbstractAutoScanProxy#getAdvicesAndAdvisorsForBean
是怎么获取拦截器类的。
- 判断当前类是否在扫描包的目录下
- 获取接口或者实现类的拦截器
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
boolean scanPackagesEnabled = scanPackagesEnabled();
// scanPackagesEnabled=false,表示“只扫描指定目录”的方式未开启,则不会对扫描到的bean进行代理预先判断
if (scanPackagesEnabled) {
boolean scanPackagesContained = scanPackagesContained(beanClass);
// 如果beanClass的类路径,未包含在扫描目录中,返回DO_NOT_PROXY
if (!scanPackagesContained) {
return DO_NOT_PROXY;
}
}
// 根据Bean名称获取Bean对象
Object bean = beanMap.get(beanName);
// 获取最终目标类
Class<?> targetClass = null;
if (bean != null /* && AopUtils.isCglibProxy(bean) */) {
targetClass = AopProxyUtils.ultimateTargetClass(bean);
} else {
targetClass = beanClass;
}
// Spring容器扫描实现类
if (!targetClass.isInterface()) {
// 扫描接口(从实现类找到它的所有接口)
if (targetClass.getInterfaces() != null) {
for (Class<?> targetInterface : targetClass.getInterfaces()) {
Object[] proxyInterceptors = scanAndProxyForTarget(targetInterface, beanName, false);
if (proxyInterceptors != DO_NOT_PROXY) {
return proxyInterceptors;
}
}
}
// 扫描实现类(如果接口上没找到注解, 就找实现类的注解)
Object[] proxyInterceptors = scanAndProxyForTarget(targetClass, beanName, true);
if (proxyInterceptors != DO_NOT_PROXY) {
return proxyInterceptors;
}
}
return DO_NOT_PROXY;
}
AbstractAutoScanProxy#scanAndProxyForTarget
,根据代理模式,获取类上的或者方法上的注解
protected Object[] scanAndProxyForTarget(Class<?> targetClass, String beanName, boolean proxyTargetClass) {
String targetClassName = targetClass.getCanonicalName();
Object[] interceptors = getInterceptors(targetClass);
// 排除java开头的接口,例如java.io.Serializable,java.io.Closeable等,执行不被代理
if (StringUtils.isNotEmpty(targetClassName) && !targetClassName.startsWith("java.")) {
// 避免对同一个接口或者类扫描多次
Boolean proxied = proxyMap.get(targetClassName);
if (proxied != null) {
if (proxied) {
return interceptors;
}
} else {
Object[] proxyInterceptors = null;
switch (proxyMode) {
// 只通过扫描到接口名或者类名上的注解后,来确定是否要代理
case BY_CLASS_ANNOTATION_ONLY:
proxyInterceptors = scanAndProxyForClass(targetClass, targetClassName, beanName, interceptors, proxyTargetClass);
break;
// 只通过扫描到接口或者类方法上的注解后,来确定是否要代理
case BY_METHOD_ANNOTATION_ONLY:
proxyInterceptors = scanAndProxyForMethod(targetClass, targetClassName, beanName, interceptors, proxyTargetClass);
break;
// 上述两者都可以
case BY_CLASS_OR_METHOD_ANNOTATION:
Object[] classProxyInterceptors = scanAndProxyForClass(targetClass, targetClassName, beanName, interceptors, proxyTargetClass);
// 没有接口或者类名上扫描到目标注解,那么扫描接口或者类的方法上的目标注解
Object[] methodProxyInterceptors = scanAndProxyForMethod(targetClass, targetClassName, beanName, interceptors, proxyTargetClass);
if (classProxyInterceptors != DO_NOT_PROXY || methodProxyInterceptors != DO_NOT_PROXY) {
proxyInterceptors = interceptors;
} else {
proxyInterceptors = DO_NOT_PROXY;
}
break;
}
// 是否需要代理
proxyMap.put(targetClassName, Boolean.valueOf(proxyInterceptors != DO_NOT_PROXY));
if (proxyInterceptors != DO_NOT_PROXY) {
// 是接口代理还是类代理
proxyTargetClassMap.put(beanName, proxyTargetClass);
/*LOG.info("------------ Matrix Proxy Information -----------");
Class<? extends MethodInterceptor>[] commonInterceptorClasses = getCommonInterceptors();
if (ArrayUtils.isNotEmpty(commonInterceptorClasses)) {
LOG.info("Class [{}] is proxied by common interceptor classes [{}], proxyTargetClass={}", targetClassName, ProxyUtil.toString(commonInterceptorClasses), proxyTargetClass);
}
String[] commonInterceptorNames = getCommonInterceptorNames();
if (ArrayUtils.isNotEmpty(commonInterceptorNames)) {
LOG.info("Class [{}] is proxied by common interceptor beans [{}], proxyTargetClass={}", targetClassName, ProxyUtil.toString(commonInterceptorNames), proxyTargetClass);
}
if (proxyInterceptors != PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS && ArrayUtils.isNotEmpty(proxyInterceptors)) {
LOG.info("Class [{}] is proxied by additional interceptors [{}], proxyTargetClass={}", targetClassName, proxyInterceptors, proxyTargetClass);
}
LOG.info("-------------------------------------------------");*/
}
return proxyInterceptors;
}
}
return DO_NOT_PROXY;
}
AbstractAutoScanProxy#getInterceptors
,获取拦截器。优先执行getAdditionalInterceptors
获取拦截器,获取不到再执行getCommonInterceptors
。
protected Object[] getInterceptors(Class<?> targetClass) {
Object[] interceptors = getAdditionalInterceptors(targetClass);
if (ArrayUtils.isNotEmpty(interceptors)) {
return interceptors;
}
Class<? extends MethodInterceptor>[] commonInterceptorClasses = getCommonInterceptors();
String[] commonInterceptorNames = getCommonInterceptorNames();
if (ArrayUtils.isNotEmpty(commonInterceptorClasses) || ArrayUtils.isNotEmpty(commonInterceptorNames)) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
return DO_NOT_PROXY;
}
AbstractAutoScanProxy#scanAndProxyForClass
,扫描类上的注解。
AbstractAutoScanProxy#scanAndProxyForMethod
,扫描方法上的注解。
protected Object[] scanAndProxyForClass(Class<?> targetClass, String targetClassName, String beanName, Object[] interceptors, boolean proxyTargetClass) {
// 判断目标注解是否标注在接口名或者类名上
boolean proxied = false;
Class<? extends Annotation>[] classAnnotations = getClassAnnotations();
if (ArrayUtils.isNotEmpty(classAnnotations)) {
for (Class<? extends Annotation> classAnnotation : classAnnotations) {
if (targetClass.isAnnotationPresent(classAnnotation)) {
// 是否执行“注解扫描后处理”
if (scanMode == ScanMode.FOR_CLASS_ANNOTATION_ONLY || scanMode == ScanMode.FOR_CLASS_OR_METHOD_ANNOTATION) {
classAnnotationScanned(targetClass, classAnnotation);
} else {
// 如果“注解扫描后处理”不开启,没必要再往下执行循环,直接返回
return interceptors;
}
// 目标注解被扫描到,proxied赋值为true,即认为该接口或者类被代理
if (!proxied) {
proxied = true;
}
}
}
}
return proxied ? interceptors : DO_NOT_PROXY;
}
protected Object[] scanAndProxyForMethod(Class<?> targetClass, String targetClassName, String beanName, Object[] interceptors, boolean proxyTargetClass) {
// 判断目标注解是否标注在方法上
boolean proxied = false;
Class<? extends Annotation>[] methodAnnotations = getMethodAnnotations();
if (ArrayUtils.isNotEmpty(methodAnnotations)) {
for (Method method : targetClass.getDeclaredMethods()) {
for (Class<? extends Annotation> methodAnnotation : methodAnnotations) {
if (method.isAnnotationPresent(methodAnnotation)) {
// 是否执行“注解扫描后处理”
if (scanMode == ScanMode.FOR_METHOD_ANNOTATION_ONLY || scanMode == ScanMode.FOR_CLASS_OR_METHOD_ANNOTATION) {
methodAnnotationScanned(targetClass, method, methodAnnotation);
} else {
// 如果“注解扫描后处理”不开启,没必要再往下执行循环,直接返回
return interceptors;
}
// 目标注解被扫描到,proxied赋值为true,即认为该接口或者类被代理
if (!proxied) {
proxied = true;
}
}
}
}
}
return proxied ? interceptors : DO_NOT_PROXY;
}
AbstractInterceptor
,抽象拦截器定义了一堆封装好的方法,获取方法名称,代理类名,类上的注解和方法上的注解。
@Component("myInterceptor3")
public class MyInterceptor3 extends AbstractInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
String proxyClassName = getProxyClassName(invocation);
Object[] arguments = getArguments(invocation);
String proxiedClassName = getProxiedClassName(invocation);
Class<?>[] proxiedInterfaces = getProxiedInterfaces(invocation);
Annotation[] classAnnotations = getProxiedClassAnnotations(invocation);
String methodName = getMethodName(invocation);
Annotation[] methodAnnotations = getMethodAnnotations(invocation);
String[] parameterNames = getMethodParameterNames(invocation);
}
}
代理模式:根据类上或者方法上的注解来生成代理
扫描模式:根据类上或者方法上的注解来执行methodAnnotationScanned
或者classAnnotationScanned
。
Spring Registrar机制
实现象
@FeignClient
注解那样,只有接口没有实现类,就能实现注入和动态代理。
EnableMyAnnotation
注入MyRegistrar
。
MyRegistrar
继承了AbstractRegistrar
,AbstractRegistrar
实现了ImportBeanDefinitionRegistrar
。
- 根据
MyRegistrar
配置的getAnnotationClass
注解类
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
registerAnnotations(metadata, registry);
}
public void registerAnnotations(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
ClassPathScanningCandidateComponentProvider scanner = getScanner();
scanner.setResourceLoader(this.resourceLoader);
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(getAnnotationClass());
scanner.addIncludeFilter(annotationTypeFilter);
Set<String> basePackages = getBasePackages(metadata);
for (String basePackage : basePackages) {
Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);
for (BeanDefinition candidateComponent : candidateComponents) {
if (candidateComponent instanceof AnnotatedBeanDefinition) {
// verify annotated class is an interface
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(getAnnotationClass().getCanonicalName());
registerAnnotation(registry, annotationMetadata, attributes);
}
}
}
}
AbstractRegistrar#getBasePackages
,根据getEnableAnnotationClass
获取扫描包的路径。获取使用EnableMyAnnotation
注解的包名。
protected Set<String> getBasePackages(AnnotationMetadata importingClassMetadata) {
Map<String, Object> attributes = importingClassMetadata.getAnnotationAttributes(getEnableAnnotationClass().getCanonicalName());
Set<String> basePackages = new HashSet<>();
for (String pkg : (String[]) attributes.get("value")) {
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
for (String pkg : (String[]) attributes.get("basePackages")) {
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
for (Class<?> clazz : (Class[]) attributes.get("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(importingClassMetadata.getClassName()));
}
return basePackages;
}
AbstractRegistrar#registerAnnotation
,根据配置的getBeanClass
和getInterceptor(beanDefinition.getPropertyValues())
,生成MyRegistrarFactoryBean
实例,配置拦截器和接口的属性,customize
将注解的属性数据配置在实体类,以及类名。
private void registerAnnotation(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
String className = annotationMetadata.getClassName();
LOG.info("Found annotation [{}] in {} ", getAnnotationClass().getSimpleName(), className);
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(getBeanClass());
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
customize(registry, annotationMetadata, attributes, definition);
try {
definition.addPropertyValue("interfaze", Class.forName(className));
} catch (ClassNotFoundException e) {
LOG.error("Get interface for name error", e);
}
definition.addPropertyValue("interceptor", getInterceptor(beanDefinition.getPropertyValues()));
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
String alias = className;
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[] { alias });
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}
RegistrarFactoryBean
实现了FactoryBean
,Spring容器获取到的就是proxy
;实现了InitializingBean
,调用代理类proxyFactory.getProxy(classLoader)
获取到代理类。
public class RegistrarFactoryBean implements ApplicationContextAware, FactoryBean<Object>, InitializingBean, BeanClassLoaderAware {
private ApplicationContext applicationContext;
private Class<?> interfaze;
private MethodInterceptor interceptor;
private Object proxy;
private ClassLoader classLoader;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
@Override
public Object getObject() throws Exception {
return proxy;
}
@Override
public Class<?> getObjectType() {
return interfaze;
}
@Override
public boolean isSingleton() {
return false;
}
@Override
public void afterPropertiesSet() throws Exception {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.addInterface(interfaze);
proxyFactory.addAdvice(interceptor);
proxyFactory.setOptimize(false);
proxy = proxyFactory.getProxy(classLoader);
}
}
总结一下:拦截注解,生成对应接口的代理类。所以如果标注的接口有实现,需要标注@Primary
。
Spring Import Selector机制
实现象
@EnableCircuitBreaker
注解那样,入口加上@EnableMyAnnotation
,自动初始化对应的Configuration。
EnableMyAnnotation
注入了EnableMyAnnotationImportSelector
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableMyAnnotationImportSelector.class)
public @interface EnableMyAnnotation {
boolean extension() default true;
}
EnableMyAnnotationImportSelector
,调用父类的selectImports
。判断注解上extension
属性值,如果为true,加载MyConfigurationExtension
,否则环境变更存入extension.enabled=false
@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableMyAnnotationImportSelector extends AbstractImportSelector<EnableMyAnnotation> {
// 如下方法适合EnableXXX注解上带有参数的情形,一般用不到
@Override
public String[] selectImports(AnnotationMetadata metadata) {
// 获取父类的Configuration列表
String[] imports = super.selectImports(metadata);
// 从注解上获取参数
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(getAnnotationClass().getName(), true));
boolean extension = attributes.getBoolean("extension");
if (extension) {
// 如果EnableMyAnnotation注解上的extension为true,那么去装载MyConfigurationExtension,即初始化里面的MyBeanExtension
List<String> importsList = new ArrayList<>(Arrays.asList(imports));
importsList.add(MyConfigurationExtension.class.getCanonicalName());
imports = importsList.toArray(new String[0]);
} else {
// 如果EnableMyAnnotation注解上的extension为false,那么你可以把该参数动态放到属性列表里
Environment environment = getEnvironment();
if (ConfigurableEnvironment.class.isInstance(environment)) {
ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) environment;
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
map.put("extension.enabled", false);
MapPropertySource propertySource = new MapPropertySource("nepxion", map);
configurableEnvironment.getPropertySources().addLast(propertySource);
}
}
return imports;
}
}
AbstractImportSelector#selectImports
,用Spring SPI加载指定的注解类。而注解类的获取是获取子类上面的泛型。
protected AbstractImportSelector() {
this.annotationClass = (Class<T>) GenericTypeResolver.resolveTypeArgument(this.getClass(), AbstractImportSelector.class);
}
@Override
public String[] selectImports(AnnotationMetadata metadata) {
if (!isEnabled()) {
return new String[0];
}
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(this.annotationClass.getName(), true));
Assert.notNull(attributes, "No " + getSimpleName() + " attributes found. Is " + metadata.getClassName() + " annotated with @" + getSimpleName() + "?");
// Find all possible auto configuration classes, filtering duplicates
List<String> factories = new ArrayList<>(new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(this.annotationClass, this.beanClassLoader)));
if (factories.isEmpty() && !hasDefaultFactory()) {
throw new IllegalStateException("Annotation @" + getSimpleName() + " found, but there are no implementations. Did you forget to include a starter?");
}
if (factories.size() > 1) {
// there should only ever be one DiscoveryClient, but there might be more than one factory
LOG.warn("More than one implementation " + "of @" + getSimpleName() + " (now relying on @Conditionals to pick one): " + factories);
}
return factories.toArray(new String[factories.size()]);
}