用 Spring 以编程方式创建 AOP 代理很容易。这让你可以在 不依赖 Spring IoC 的情况下使用 Spring AOP。
目标对象实现的接口会自动被代理。下面的列表显示了为目标对象创建一个代理,其中有一个拦截器和一个顾问:
ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl);factory.addAdvice(myMethodInterceptor);factory.addAdvisor(myAdvisor);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 容器了
package cn.mrcode.study.springdocsread.aspect;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import org.springframework.aop.framework.ProxyFactory;import org.springframework.aop.interceptor.DebugInterceptor;import cn.mrcode.study.springdocsread.aspect.persion.MyAdvisor;import cn.mrcode.study.springdocsread.aspect.persion.Person;import cn.mrcode.study.springdocsread.aspect.persion.PersonImpl;/*** @author mrcode*/public class DemoTest {public static void main(String[] args) {final PersonImpl person = new PersonImpl();// 传入目标类ProxyFactory factory = new ProxyFactory(person);// 添加 advice,其实也是拦截器factory.addAdvice(new DebugInterceptor());factory.addAdvisor(myAdvisor());factory.setProxyTargetClass(true);Person personProxy = (Person) factory.getProxy();personProxy.getName();System.out.println(personProxy);}public static MyAdvisor myAdvisor() {// 该顾问没有设置 pointcut,默认就是拦截所有的方法final MyAdvisor myAdvisor = new MyAdvisor();myAdvisor.setSomeProperty("Custom string property value");// 给该顾问配置一个拦截器,这里使用了方法拦截器,每个方法被调用的时候都会进入这个 advicemyAdvisor.setAdvice(new MethodInterceptor() {@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("自定义方法拦截");return invocation.proceed();}});return myAdvisor;}}
