根据spring-framework-reference,DefaultAdvisorAutoProxyCreator创建代理更加通用强大,使用此机制包括:
a.指定一个DefaultAdvisorAutoProxyCreator Bean的定义.
b.指定在相同或相关的上下文中任意数量的Advisor.注意,必须是Advisor,而不仅仅是interceptor或advice.这是必要的,因为必须有一个切点被评估,以便检查每个advice到候选bean定义是否合格.
下面举个应用例子.
1.主要依赖(略)
和BeanNameAutoProxyCreator一样,DefaultAdvisorAutoProxyCreator也是一个BeanPostProcessor.它在Bean实例化随后,调用回调org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization进行后期处理来完成代理的创建.
其中AbstractAutoProxyCreator是BeanNameAutoProxyCreator的超类,BeanNameAutoProxyCreator没有重写postProcessAfterInitialization方法.下面看看这个方法:
看看wrapIfNecessary方法:
先看看org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean方法(与BeanNameAutoProxyCreator不同),此处就可以找到在AppConfig配置的NameMatchMethodPointcutAdvisor.
a.指定一个DefaultAdvisorAutoProxyCreator Bean的定义.
b.指定在相同或相关的上下文中任意数量的Advisor.注意,必须是Advisor,而不仅仅是interceptor或advice.这是必要的,因为必须有一个切点被评估,以便检查每个advice到候选bean定义是否合格.
下面举个应用例子.
1.主要依赖(略)
2.具体类.
@Configuration
public class AppConfig {
//要创建代理的目标Bean
@Bean
public UserService userService(){
return new UserServiceImpl();
}
//创建Advice
@Bean
public Advice myMethodInterceptor(){
return new MyMethodInterceptor();
}
//使用Advice创建Advisor
@Bean
public NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisor(){
NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisor=new NameMatchMethodPointcutAdvisor();
nameMatchMethodPointcutAdvisor.setMappedName("pri*");
nameMatchMethodPointcutAdvisor.setAdvice(myMethodInterceptor());
return nameMatchMethodPointcutAdvisor;
}
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
return new DefaultAdvisorAutoProxyCreator();
}
}
public interface UserService {
void print();
}
public class UserServiceImpl implements UserService {
public void print(){
System.out.println(getClass()+"#print");
}
}
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println(getClass()+"调用方法前");
Object ret=invocation.proceed();
System.out.println(getClass()+"调用方法后");
return ret;
}
}
3.测试
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext=new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService= applicationContext.getBean(UserService.class);
userService.print();
}
}
跟踪下实现:
和BeanNameAutoProxyCreator一样,DefaultAdvisorAutoProxyCreator也是一个BeanPostProcessor.它在Bean实例化随后,调用回调org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization进行后期处理来完成代理的创建.
其中AbstractAutoProxyCreator是BeanNameAutoProxyCreator的超类,BeanNameAutoProxyCreator没有重写postProcessAfterInitialization方法.下面看看这个方法:
看看wrapIfNecessary方法:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//这个bean是否匹配要创建代理也是在这个方法.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//关键代码在这里
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
先看看org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean方法(与BeanNameAutoProxyCreator不同),此处就可以找到在AppConfig配置的NameMatchMethodPointcutAdvisor.
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
剩下的就与BeanNameAutoProxyCreator创建代理类似了.