用 Spring 以编程方式创建 AOP 代理很容易。这让你可以在 不依赖 Spring IoC 的情况下使用 Spring AOP

目标对象实现的接口会自动被代理。下面的列表显示了为目标对象创建一个代理,其中有一个拦截器和一个顾问:

  1. ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl);
  2. factory.addAdvice(myMethodInterceptor);
  3. factory.addAdvisor(myAdvisor);
  4. MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy();

第一步是构造一个 org.springframework.aop.framework.ProxyFactory类型的对象。你可以像前面的例子那样用一个目标对象来创建它,或者在另一个构造函数中指定要代理的接口。

你可以添加 advice(用拦截器作为一种专门的 advice)、顾问或两者,并在 ProxyFactory 的生命中操纵它们。如果你添加一个IntroductionInterceptionAroundAdvisor,你可以使代理实现额外的接口。

在 ProxyFactory 上还有一些方便的方法(继承自 AdvisedSupport),可以让你添加其他的 advice 类型,比如 before 和 throws advice。 AdvisedSupport 是 ProxyFactory 和 ProxyFactoryBean 的超类。

:::tips 在大多数应用中,将 AOP 代理的创建与 IoC 框架相结合是最佳实践。我们建议你用 AOP 将配置从 Java 代码中外部化,一般来说,你应该这样做。 :::

例子

其实和前面 ProxyFactoryBean 的例子一样,只不过不使用 IOC 容器了

  1. package cn.mrcode.study.springdocsread.aspect;
  2. import org.aopalliance.intercept.MethodInterceptor;
  3. import org.aopalliance.intercept.MethodInvocation;
  4. import org.springframework.aop.framework.ProxyFactory;
  5. import org.springframework.aop.interceptor.DebugInterceptor;
  6. import cn.mrcode.study.springdocsread.aspect.persion.MyAdvisor;
  7. import cn.mrcode.study.springdocsread.aspect.persion.Person;
  8. import cn.mrcode.study.springdocsread.aspect.persion.PersonImpl;
  9. /**
  10. * @author mrcode
  11. */
  12. public class DemoTest {
  13. public static void main(String[] args) {
  14. final PersonImpl person = new PersonImpl();
  15. // 传入目标类
  16. ProxyFactory factory = new ProxyFactory(person);
  17. // 添加 advice,其实也是拦截器
  18. factory.addAdvice(new DebugInterceptor());
  19. factory.addAdvisor(myAdvisor());
  20. factory.setProxyTargetClass(true);
  21. Person personProxy = (Person) factory.getProxy();
  22. personProxy.getName();
  23. System.out.println(personProxy);
  24. }
  25. public static MyAdvisor myAdvisor() {
  26. // 该顾问没有设置 pointcut,默认就是拦截所有的方法
  27. final MyAdvisor myAdvisor = new MyAdvisor();
  28. myAdvisor.setSomeProperty("Custom string property value");
  29. // 给该顾问配置一个拦截器,这里使用了方法拦截器,每个方法被调用的时候都会进入这个 advice
  30. myAdvisor.setAdvice(new MethodInterceptor() {
  31. @Override
  32. public Object invoke(MethodInvocation invocation) throws Throwable {
  33. System.out.println("自定义方法拦截");
  34. return invocation.proceed();
  35. }
  36. });
  37. return myAdvisor;
  38. }
  39. }