用 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");
// 给该顾问配置一个拦截器,这里使用了方法拦截器,每个方法被调用的时候都会进入这个 advice
myAdvisor.setAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("自定义方法拦截");
return invocation.proceed();
}
});
return myAdvisor;
}
}