文章目录
- 前言
- 一、AnnotationAwareAspectJAutoProxyCreator后置处理器的创建
- 二、在AnnotationAwareAspectJAutoProxyCreator后置处理器方法中创建代理(jdk或cglib)
- 2.1、创建CglibAopProxy或JdkDynamicAopProxy对象
- 2.2、 执行代理方法
- 三、springaop代理类创建过程
- 四、springAop代理类执行过程
- 五、springAop后置处理器查找advisor过程
- 六、自己实现一个aop注解
- 1、advisor
- 2、advice
- 3、pointcut
- 4、ClassFilter
- 5、MethodMatcher
- 七、DeclareParents注解的使用
- 六、使用JdkDynamicAopProxy
- 总结
前言
暂无
一、AnnotationAwareAspectJAutoProxyCreator后置处理器的创建
spring.factories内配置的自动配置类AopAutoConfiguration,类上ConditionalOnClass注解内容EnableAspectJAutoProxy注解,EnableAspectJAutoProxy注解上方@Import导入了AspectJAutoProxyRegistrar类,为ImportBeanDefinitionRegistrar接口的实现类。在CongifurationClassParser解析@Import注解时调用ImportBeanDefinitionRegistrar接口的方法,AnnotationAwareAspectJAutoProxyCreator的beanDefinition会被注册到spring
二、在AnnotationAwareAspectJAutoProxyCreator后置处理器方法中创建代理(jdk或cglib)
2.1、创建CglibAopProxy或JdkDynamicAopProxy对象
AnnotationAwareAspectJAutoProxyCreator间接实现了SmartInstantiationAwareBeanPostProcessor接口,所以在bean创建完成后会调用其后置处理方法,在后置处理器方法中使用ProxyFactory(extends ProxyCreatorSupport).getProxy()来创建代理,在ProxyFactory的父类ProxyCreatorSupport默认构造函数里new DefaultAopProxyFactory();调用DefaultAopProxyFactory的createAopProxy方法,返回CglibAopProxy或JdkDynamicAopProxy对象,
AbstractAutoProxyCreator创建ProxyFactory时候,为ProxyFactory设置Advisor实现类(包装了Advice(AspectJAroundAdvice)和pointcut)
2.2、 执行代理方法
CglibAopProxy在getProxy创建代理类的时候,设置了DynamicAdvisedInterceptor回调,调用回调的intercept方法时,new CglibMethodInvocation,调用其proceed方法。
ReflectiveMethodInvocation.proceed---->AspectJAroundAdvice.invoke,ProceedingJoinPoint作为@Around方法的参数,其实是将ReflectiveMethodInvocation包装到了ProceedingJoinPoint实现类里面,调用ProceedingJoinPoint.proceed实际上是调用ReflectiveMethodInvocation.proceed,当创建的代理类的拦截器都执行完以后就执行默认的@Around修饰的方法。
三、springaop代理类创建过程
四、springAop代理类执行过程
五、springAop后置处理器查找advisor过程
六、自己实现一个aop注解
1、advisor
public class MyAopAspectjAdvisor implements PointcutAdvisor {
private Pointcut pointcut = new MyAopAspectJPointcut();
private Advice advice = new MyAopAspectjAdvice();
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
@Override
public Advice getAdvice() {
return this.advice;
}
@Override
public boolean isPerInstance() {
return true;
}
public void setPointcut(Pointcut pointcut) {
this.pointcut = pointcut;
}
public void setAdvice(Advice advice) {
this.advice = advice;
}
}
2、advice
public class MyAopAspectjAdvice implements MethodInterceptor {
private static final Logger log = LoggerFactory.getLogger(MyAopAspectjAdvice.class);
public MyAopAspectjAdvice(){
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
log.info("-------------------------------------------------------------------自定义增强器");
return invocation.proceed();
}
}
3、pointcut
public class MyAopAspectJPointcut implements Pointcut {
@Override
public ClassFilter getClassFilter() {
return ClassFilter.TRUE;
}
@Override
public MethodMatcher getMethodMatcher() {
return new MyAopMethodMatcher();
}
}
4、ClassFilter
这里使用默认的ClassFilter,ClassFilter.TRUE
5、MethodMatcher
public class MyAopMethodMatcher implements MethodMatcher {
@Override
public boolean matches(Method method, Class<?> targetClass) {
Proxy annotation = AnnotationUtils.findAnnotation(method, Proxy.class);
return annotation != null && annotation.isProxy();
}
@Override
public boolean isRuntime() {
return false;
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
return false;
}
}
七、DeclareParents注解的使用
DeclareParents和pointcut一样也会为表达式匹配的类生成代理,会为匹配的类增加一个接口实现,
真正调用这个接口的实现是注解里声明的defaultImpl实现类对应的方法。(DeclareParentsAdvisor)
@Aspect
@Component
public class ProxyTestConfig {
@DeclareParents(value = "com.springboot.service.*", defaultImpl = TestDeclareParentImpl.class)
private ITestDeclareParent testDeclareParent;
@Pointcut("execution(* com.springboot.service..*.*(..))")
public void around() {
}
@Around("around()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
logger.info("around start......");
return joinPoint.proceed();
}
}
public interface ITestDeclareParent {
String hello();
}
// 并不需要放入spring容器
public class TestDeclareParentImpl implements ITestDeclareParent{
@Override
public String hello(){
System.out.println("===============================================================");
return "zs";
}
}
@RunWith(SpringRunner.class)
@SpringBootTest(classes={SpringBootStarterApplication.class})
public class SpringbootTest {
@Autowired
private IProxyTestService IProxyTestService;
@Test
public void testProxy() {
((ITestDeclareParent)IProxyTestService).hello();
}
}
六、使用JdkDynamicAopProxy
在new ProxyFactory时候将实现了接口的类传入即可
注意:当直接传入advice时,proxyFactory会将advice包装到DefaultPointcutAdvisor类中,new DefaultPointcutAdvisor(advice),
而这个类内部的pointcut不管ClassFilter还是MethodMatcher,其matches方法都默认返回true,即对所有的类的所有方法都进行代理。
这个advice对每个类都进行调用。
public void testProxy() {
ProxyFactory factory = new ProxyFactory(new ProxyTestServiceImpl());
factory.addAdvice((MethodBeforeAdvice) (method, args1, target) ->
System.out.println("你被拦截了:方法名为:" + method.getName() + " 参数为--" + Arrays.asList(args1)));
factory.getProxy();
}