首先了解下AOP使用
1.创建一个用于拦截的bean
@Component
@Slf4j
public class TestBean {
private String testStr = "testStr";
public String getTestStr() {
return testStr;
}
public void setTestStr(String testStr) {
this.testStr = testStr;
}
public void test() {
log.info("test");
}
}
2.创建Advisor
@Aspect
@Slf4j
@Component
public class AspectJTest {
@Pointcut("execution(* *.test(..))")
public void test(){}
@Before("test()")
public void beforeTest() {
log.info("beforeTest");
}
@After("test()")
public void afterTest() {
log.info("afterTest");
}
@Around("test()")
public Object aroundTest(ProceedingJoinPoint p) {
log.info("before1");
Object o = null;
try {
o = p.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
log.info("after1");
return o;
}
}
3.测试
4.结果
5.maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
如果使用的spring那么需要xml中加入<aop:aspectj-autoproxy/>
,配置文件声明后,就会支持注解AOP。
springboot用这个注解@EnableAspectJAutoProxy
注册了一个AspectJAutoProxyBeanDefinitionParser解析器,解析标签的。
1.registerAspectJAnnotationAutoProxyCreatorIfNecessary方法
来具体看下如何创建自动代理创建器。cls为AnnotationAwareAspectJAutoProxyCreator.class
2.useClassProxyingIfNecessary方法
proxy-target-class:使用JDK或CGLIB创建代理对象。如果被代理的目标对象实现了至少一个接口,则使用JDK代理。若没有实现任何接口,则创建一个CGLIB代理。
具体看一下AnnotationAwareAspectJAutoProxyCreator类。
可以看到他实现了postProcessAfterInitialization方法,继承的是BPP类
wrapIfNecessary方法
getAdvicesAndAdvisorsForBean获取增强方法
findEligibleAdvisors方法,获取出bean所适用的增强器。
findCandidateAdvisors获取增强器。
buildAspectJAdvisors方法用于获取注解形式的增强器。
实现步骤
- 获取所有的beanName。
- 遍历所有的beanName,找到带有AspectJ注解的类。
- 提取出这些类的增强器。
- 将结果加入缓存当中。
获取到的增强方法都会放到advisorsCache或aspectFactoryCache中。
最后通过aspectName来从cache中取出,放到统一的List集合中,返回。这样就获取了所有的增强方法。
然我们看下增强器的获取this.advisorFactory.getAdvisors(factory)
。getAdvisorMethods主要获取没有声明为pointcut的方法。
getAdvisorMethods根据切面类来获取增强方法
getAdvisor根据增强方法构建出增强器。
InstantiationModelAwarePointcutAdvisorImpl方法,用于根据切点信息生产增强器。在封装过程中只是简单地将信息封装在类的实例中。
再回顾一下获取需要的增强器,先找到所有的增强器,然后再找到该bean适用的增强器。
findAdvisorsThatCanApply找到bean适用的增强器。
获取了对应bean的所有增强器后,就可以进行代理的创建了。
再看一下代理创建器中的bpp before干了哪些事情。
createProxy方法
1.获取当前类中的属性
2.添加代理接口
3.封装Advisor加入到ProxyFactroy中
4.设置要代理的类
5.提供定制函数,子类可以在此函数中进行对ProxyFactory的进一步封装。
6.进行获取代理操作。
createAopProxy方法创建代理类。
让我们接下来看看如何获取代理类。JDK、CGLIB
public interface UserService {
/**
* 目标方法
*/
public abstract void add();
}
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("------add------");
}
}
public class MyInvocationHandler implements InvocationHandler {
// 目标对象
private Object target;
public MyInvocationHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("---------before--------");
// 执行目标方法
Object result = method.invoke(target, objects);
System.out.println("---------after---------");
return result;
}
/**
* 获取目标对象的代理对象
* @return
*/
public Object getProxy() {
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), this);
}
}
public class ProxyTest {
public static void testProxy() {
UserService userService = new UserServiceImpl();
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(userService);
UserService proxy = (UserService) myInvocationHandler.getProxy();
proxy.add();
}
public static void main(String[] args) {
testProxy();
}
}
JdkDynamicAopProxy肯定是实现了InvocationHandler接口,实现了invoke方法。
invoke方法最后会通过拦截器链来依次执行每一个增强器,顺序不固定,然后最后会执行目标方法。
CGLIB看不下去了!!!!我太难了