1. Spring中的AOP需要手动开启
在Spring中,如果我们采用注解的方式进行AOP,则需要手动开启Spring的AOP支持,如下例子:
① 定义Spring的配置类,主要声明需要扫描的包路径,并且打开AOP功能
@Configuration
@ComponentScan("com.single")
@EnableAspectJAutoProxy
public class SpringConfig {
}
@EnableAspectJAutoProxy该注解即为打开AOP的注解,我们也可以通过该注解选择动态代理的方式,默认情况下,Spring采用JDK的动态代理,我们可以点进该注解看下,请重点看下第一个属性的注释:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
②自定义aop注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface AspectAnnotation {
}
③编写切面类、切点、以及增强
@Component
@Aspect
public class AspectTest {
@Pointcut("@annotation(com.single.annotation.AspectAnnotation)")
public void pointCut() {}
@Before("pointCut()")
public void before(JoinPoint point) {
System.out.println("前置增强");
}
@After("pointCut()")
public void after() {
System.out.println("后置增强");
}
}
④在需要被增强的方法上添加自定义注解,方法所在bean一定要交给Spring管理
@Service
public class TestService {
public TestService() {
System.out.println("TestService is created...");
}
@AspectAnnotation
public void test() {
System.out.println("init......");
}
}
⑤启动容器并调用方法
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
TestService bean = ctx.getBean(TestService.class);
bean.test();
}
}
⑥结果

2. SpringBoot中的AOP默认开启,并采用Cglib代理方式
在SpringBoot中,AOP的使用与上述没有区别,只不过不需要我们手动开启AOP功能了,主要是因为SpringBoot的自动装配,如果你读过SpringBoot的源码,相比你一定会知道在spring-boot-autoconfigure的META-INF下有一个spring.factories文件,它里面指明了很多需要自动装配的配置类的路径,在启动的时候会自动将这些配置类中定义的bean装配到IOC中,原理不多说了,感兴趣的可以去研究一下。
我们来看一下这个文件

可以看到自动配置中有一个AOP的配置类,找到它,源码如下:

可以看到第53行和61行都用了@EnableAspectJAutoProxy注解,但是这个配置生效的前提条件是由@ConditionalOnProperty注解来控制的,此处还是涉及到了SpringBoot自动装配的原理了,因为它是自动装配,那么外部组件那么多,如果都要自动装配,那岂不是要加载很多无用的bean吗,所以它肯定设定的bean被加载的条件,在META-INFO/spring-configuration-metadata.json中我们可以找到如下信息
{
"name": "spring.aop.proxy-target-class",
"type": "java.lang.Boolean",
"description": "Whether subclass-based (CGLIB) proxies are to be created (true), as opposed to standard Java interface-based proxies (false).",
"defaultValue": true
},
上述说明就是spring.aop.proxy-target-class的默认值为true,结合@ConditionalOnProperty注解里的参数,可以知道JDK的动态代理配置不生效,因为它的加载条件是false,所以SpringBoot在启动的时候会自动开启AOP功能并采用Cglib方式进行动态代理