Spring实现+后台原理(MethodInterceptor)MethodInterceptor
MethodInterceptor是AOP项⽬中的(注:不是动态代理),区别与HandlerInterceptor拦截⽬标时请求,它拦截的⽬标是⽅法。实现MethodInterceptor⼤致也分为两种:
(1)MethodInterceptor接⼝;
(2)利⽤AspectJ的注解配置;
MethodInterceptor接⼝:
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class MethodInvokeInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("before ");
Object object = methodInvocation.proceed();
System.out.println("after ");
return object;
}
}
<!-- demo -->
<bean id="methodInvokeInterceptor" class="com.paic.phssp.hod.MethodInvokeInterceptor"/>
<aop:config>
<!--切⼊点,controlller -->
<aop:pointcut id="pointcut_test" expression="execution(* com.paic.ller..*.*(..))"/>
<!--在该切⼊点使⽤⾃定义 ,按照先后顺序执⾏ -->
<aop:advisor pointcut-ref="pointcut_test" advice-ref="methodInvokeInterceptor"/>
</aop:config>
<!-- ⾃动扫描使⽤了aspectj注解的类 -->
<aop:aspectj-autoproxy/>
执⾏:
AspectJ的注解
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class AutoAspectJInterceptor {
@Around("execution (* com.paic.ller..*.*(..))")
public Object around(ProceedingJoinPoint point) throws Throwable{
System.out.println("AutoAspectJInterceptor ");
Object object = point.proceed();
System.out.println("AutoAspectJInterceptor ");
return object;
}
}
运⾏结果:
AutoAspectJInterceptor
>>>>:isAuthenticated=false
AutoAspectJInterceptor
简单介绍下关键词:
AOP=Aspect Oriented Program ⾯向切⾯(⽅⾯/剖⾯)编程
Advice(通知):把各组件中公共业务逻辑抽离出来作为⼀个独⽴的组件
Weave(织⼊) : 把抽离出来的组件(Advice),使⽤到需要使⽤该逻辑地⽅的过程。JoinPoint (连接点): Advice 组件可以weave的特征点。
PointCut(切⼊点):⽤来明确Advice需要织⼊的连接点
springboot和过滤器Aspect(切⾯):Aspect=Advice + PointCut
通知类型
@Before 在切点⽅法之前执⾏
@After 在切点⽅法之后执⾏
@AfterReturning 切点⽅法返回后执⾏
@AfterThrowing 切点⽅法抛异常执⾏
@Around环绕通知
执⾏顺序:
@Around环绕通知
@Before通知执⾏
@Before通知执⾏结束
@Around环绕通知执⾏结束
@After后置通知执⾏了!
@AfterReturning
切⾯设置:
可以使⽤&&、||、!、三种运算符来组合切点表达式
execution表达式:
"execution(public * com.ller.*.*(..))"
*只能匹配⼀级路径
..可以匹配多级,可以是包路径,也可以匹配多个参数
+ 只能放在类后⾯,表明本类及所有⼦类
within(类路径) 配置指定类型的类实例,同样可以使⽤匹配符
within(com.xhx.springboot..*)
@within(annotationType) 匹配带有指定注解的类(注:与上不同)
"@within(org.springframework.stereotype.Component)"
@annotation(annotationType) 匹配带有指定注解的⽅法
"@annotation(IDataSource)"
其中:IDataSource为⾃定义注解
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface IDataSource {
String value() default "dataSource";
}
下⾯分析下Spring @Aspect :
1、注册
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
看到实现接⼝BeanPostProcessor,必然在初始化Bean前后,执⾏接⼝⽅法。
2、解析
AspectJAutoProxyBeanDefinitionParser.java#parse()⽅法
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
return null;
}
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
BeanDefinition beanDefinition = Registry(), actSource(sourceElement)); Registry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
3、具体实现
上⾯提到实现接⼝BeanPostProcessor,必然在初始化Bean前后,执⾏接⼝⽅法。看下⾯时序图:
AbstractAutoProxyCreator的postProcessAfterInitialization()⽅法。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
Class<?> targetClass = TargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
} else {
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config)); }
}
}
下午有点 。。。。
参考:
wwwblogs/davidwang456/p/5633940.html
wwwblogs/niceyoo/p/8735637.html
blog.csdn/u014634338/article/details/84144498
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论