这里通过maven插件的方式为JVM设置代理,通过-javaagent参数指定织入器类包的路径,这样就可以在类加载期将切面织入,更多关于javaagent的知识可以参考javaagent
织入目标类
/** * @author: takumiCX * @create: 2018-12-19 **/ @Component public class LtwBean { public void test(){ System.out.println("process......."); } }只有一个test()方法,通过@Componet注解向容器注册。
切面类
/** * @author: takumiCX * @create: 2018-12-19 **/ @Aspect public class LogMethodInvokeAspect { @Pointcut("execution(public * com.takumiCX.ltw.*.*(..))") public void pointCut(){ } @Around("pointCut()") public void advise(ProceedingJoinPoint pjp) throws Throwable { Signature signature = pjp.getSignature(); System.out.println(signature+" start..... "); pjp.proceed(); System.out.println(signature+" end......"); } }@Aspect注解表示这是一个切面类
配置类
/** * @author: takumiCX * @create: 2018-12-19 **/ @Configuration @ComponentScan("com.takumiCX.ltw") @EnableLoadTimeWeaving(aspectjWeaving=AUTODETECT) public class CustomLtwConfig{ }通过@@EnableLoadTimeWeaving开启LTW功能,可以通过属性aspectjWeaving指定LTW的开启策略
ENABLED
开启LTW
DISABLED
不开启LTW
AUTODETECT
如果类路径下能读取到META-INF/aop.xml文件,则开启LTW,否则关闭
在META-INF文件夹下编写aop.xml文件
aop.xml文件内容
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd"> <aspectj> <!--要织入切面的目标类--> <weaver> <include within="com.takumiCX.ltw..*" /> </weaver> <!--切面类--> <aspects> <aspect /> </aspects> </aspectj>这样我们的Spring容器就能加载该文件读取到描述目标类和切面类的相关信息,容器在加载目标类的class文件到jvm之前,会将切面类中定义的增强逻辑织入到class文件中,真正加载到jvm中的是织入切面后的class文件,因而通过该class文件创建出的目标类的实例,不需要经过动态代理就能实现AOP相关功能。
测试类
/** * @author: takumiCX * @create: 2018-12-20 **/ @RunWith(SpringRunner.class) @SpringBootTest(classes ={CustomLtwConfig.class}) public class LTWTest { @Autowired private LtwBean ltwBean; @Test public void testLTW() throws InterruptedException { ltwBean.test(); } }最后的结果如下
方法调用前后分别记录的开始和结束的日志信息,说明我们的切面成功的织入到了目标类。但是这里可能有一个疑问,这真的是LTW(Load TimeWeaving)通过在类加载期织入切面起到的作用吗?有没有可能是LTW没起作用,是Spring AOP默认通过运行期生成动态代理的方式实现的AOP。
我们的LogMethodInvokeAspect切面类上并没有加@Component注解向容器注册,并且配置类CustomLtwConfig上也没有加@EnableAspectJAutoProxy注解开启Aspectj的运行时动态代理,所以这里基于动态代理的AOP并不会生效。
为了验证我们的想法,将aop.xml文件删除
重新运行测试代码
AOP没起到作用,说明刚才的AOP功能确实是通过LTW技术实现的。
当我们给切面类加上@Component注解,给配置类加上@EnableAspectJAutoProxy
/** * @author: takumiCX * @create: 2018-12-19 **/ @Aspect @Component public class LogMethodInvokeAspect { /** * @author: takumiCX * @create: 2018-12-19 **/ @Configuration @ComponentScan("com.takumiCX.ltw") @EnableAspectJAutoProxy @EnableLoadTimeWeaving(aspectjWeaving=AUTODETECT) public class CustomLtwConfig{ }