SpringAOP中是直接用AspectJ的的注解来使用,这些注解是AspectJ5之后引入的特性。
如不做其他设置,注解方式依旧是用的JdkDynamicAopProxy类来生成实现类,面向接口生成。
因为注解式属于AspectJ体系的,因此我们需要在配置文件中手动注册一个
AnnotationAwareAspectJAutoProxyCreator
bean来将带有@Aspect注解的bean在编译器动态生成代理类,将切面织入到代理类中。
public interface User { public void say(); }
@Component public class UserImpl implements User{ public void say() { System.out.println("hello aop!"); } }
@Aspect//注解属于AspectJ @Component//在spring中注册为bean,纳入管理 public class AnnoAspect { @Pointcut("execution(* demo.entity.User.*(..))") public void pointcut(){}; @Before("pointcut()") public void before(){ System.out.println("before run..."); } @After("pointcut()") public void after(){ System.out.println("after run..."); } @Around("pointcut()") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { proceedingJoinPoint.proceed(); System.out.println("around run..."); } @AfterThrowing("pointcut()") public void throwEx(){ System.out.println("throw ex..."); } }
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring.xml"); //getBean这次直接返回动态代理类 User user = (User)applicationContext.getBean("userImpl"); user.say();输出
before run...
hello aop!
around run...
after run...
注意我们依旧是用的接口来接受代理类。
然后看配置文件中这一个类名是太长了。。因此spring又对此进行了优化,只需要开启某个配置即可替换这个注册这个bean。
<aop:aspectj-autoproxy> 表示开启AspectJ的面向接口的动态代理生成,而不再使用spring的动态代理方式,区别就是一个是编译时生成代理类,一个是运行时生成代理类。
输出
before run... hello aop! around run... after run...
现在依旧是面向接口的,我们要使用CGLib子类代理呢。像昨天那样一样作就行了。
成功输出
before run...
hello aop!
around run...
after run...
然后仔细看我们的配置文件,以下配置和我们昨天的配置是一样的,因此我们就可以得出如下结论。
<aop:aspectj-autoproxy proxy-target-class="true" />
1.spring声明式和变成式在运行时,动态生成一个面向接口的代理子类。
2.spring的注解式是使用了AspectJ的注解,必须使用 <aop:aspectj-autoproxy />标签开启对AspectJ的支持。
在编译时,spring动态生成一个面向接口的代理子类。
3.不管是spring还是AspectJ如果要使用CGLib代理开启<aop:aspectj-autoproxy proxy-target-class="true"/>标签。
在编译时,spring动态生成一个实现类的代理子类。