Spring的AOP使用通常是通过注解方式使用,这里我想记录一下通过接口方式使用AOP功能,这样能够帮助我更加深入理解AOP原理。
一、ProxyFactory
这种方式比较底层的,脱离Spring容器管理
public class MemberService {
private String clusterName;
public MemberService() {
}
public void testMember() {
System.out.println("hello test");
}
@Override
public String toString() {
return "MemberService{" +
"clusterName='" + clusterName + '\'' +
'}';
}
}
public class App {
public static void main(String[] args) {
MemberService memberService = new MemberService();
memberService.setClusterName("hello member");
ProxyFactory factory = new ProxyFactory();
factory.setTarget(memberService);
factory.addAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before...");
Object proceed = invocation.proceed();
System.out.println("after...");
return proceed;
}
});
MemberService proxyMemberService = (MemberService)factory.getProxy();
proxyMemberService.testMember();
}
}
二、ProxyFactoryBean
MemberService类同上所示。注入ProxyFactoryBean对象即可。
@Configuration
public class AppConfig {
@Bean
public ProxyFactoryBean memberServiceProxy() {
MemberService memberService = new MemberService();
ProxyFactoryBean bean = new ProxyFactoryBean();
bean.setTarget(memberService);
bean.addAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before...");
Object proceed = invocation.proceed();
System.out.println("after...");
return proceed;
}
});
return bean;
}
}
public class App {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext("com.example");
MemberService memberServiceProxy = context.getBean("memberServiceProxy", MemberService.class);
memberServiceProxy.testMember();
}
}
三、BeanNameAutoProxyCreator
以上两种方式,都需要我们手动创建对象,并不能直接使用Spring容器内bean对象。下面这种方式是可以解决的,这里的MemberService需要用@Component进行注入
@Component
public class MemberService {
private String clusterName;
public MemberService() {
}
public void testMember() {
System.out.println("hello test");
}
@Override
public String toString() {
return "MemberService{" +
"clusterName='" + clusterName + '\'' +
'}';
}
}
@Configuration
public class AppConfig {
@Bean
public MethodInterceptor myInterceptor() {
return new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before...");
Object proceed = invocation.proceed();
System.out.println("after...");
return proceed;
}
};
}
@Bean
public BeanNameAutoProxyCreator autoProxyCreator() {
BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
beanNameAutoProxyCreator.setBeanNames("member*");//代理以member开始所有bean对象
beanNameAutoProxyCreator.setInterceptorNames("myInterceptor");//指定拦截器名字,即增强逻辑bean
return beanNameAutoProxyCreator;
}
}
四、DefaultPointcutAdvisor
这里是Advisor不是Advice,通过注入两个Bean对象,就可以增强任何类中带有test的方法,如下所示:
@Configuration
public class AppConfig {
@Bean
public DefaultPointcutAdvisor pointcutAdvisor() {
NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
pointcut.setMappedName("test*");
DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
defaultPointcutAdvisor.setPointcut(pointcut);
defaultPointcutAdvisor.setAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before...");
Object proceed = invocation.proceed();
System.out.println("after...");
return proceed;
}
});
return defaultPointcutAdvisor;
}
@Bean
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
return new DefaultAdvisorAutoProxyCreator();
}
}
@Component
public class MemberService {
private String clusterName;
public MemberService() {
}
public void testMember() {
System.out.println("hello test");
}
@Override
public String toString() {
return "MemberService{" +
"clusterName='" + clusterName + '\'' +
'}';
}
}
public class App {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext("com.example");
MemberService memberServiceProxy = context.getBean("memberService", MemberService.class);
memberServiceProxy.testMember();
}
}
五、总结
Spring提供的AOP方式有很多,这里罗列一些可能会用到的接口,其中第4个接口是最强大的,后面可以深入研究一下。