I'm collecting some SPI implementing instances using ServiceFactoryBean and ServiceListFactoryBean and auto-wiring to my service beans. Now I've created some aspects to intercept these classes to measure performance and log invocations.
I notice that spring is creating proxy for the instances captured by ServiceFactoryBean and injected into service beans. But it's not creating any proxy for the list of instances captured by ServiceListFactoryBean.
How do I tell spring to create proxy for these beans to that my aspects work?
Following is my code snippet -
Configuration which collects SPI implementations and exposes them for autowiring
@Bean
public ServiceFactoryBean faceImageStorageProvider() {
ServiceFactoryBean serviceFactoryBean = new ServiceFactoryBean();
serviceFactoryBean.setServiceType(FaceImageStorageProvider.class);
return serviceFactoryBean;
}
@Bean
public ServiceListFactoryBean notificationSenders() {
ServiceListFactoryBean serviceListFactoryBean = new ServiceListFactoryBean();
serviceListFactoryBean.setServiceType(NotificationSender.class);
return serviceListFactoryBean;
}
Aspects (This one works)
@Pointcut("execution(* com.xxx.spi.storage.FaceImageStorageProvider.*(..))")
private void anyFaceImageStorageProviderAPI() {}
(This one doesnt work)
@Pointcut("execution(* com.xxx.spi.notification.NotificationSender.*(..))")
private void anyNotificationSenderAPI() {}
Just FYI, I solved the problem by programmatically creating the proxies in following way -
@Autowired
private NotificationPerformanceLogger notificationPerformanceLogger;
@Bean
public List<NotificationSender> notificationSenders() {
LOGGER.info("Crating proxy for NotificationSender implementations");
List<NotificationSender> senders = getAvailableNotificationSenders();
LOGGER.debug("Found [{}] NotificationSender implementations", CollectionUtils.size(senders));
return createProxiedNotificationSendersAsSpringWillNotCreateProxyForThese(senders);
}
private List<NotificationSender> getAvailableNotificationSenders() {
List<NotificationSender> senders = new ArrayList<>();
try {
ServiceListFactoryBean serviceListFactoryBean = new ServiceListFactoryBean();
serviceListFactoryBean.setServiceType(NotificationSender.class);
serviceListFactoryBean.afterPropertiesSet();
senders = (List<NotificationSender>) serviceListFactoryBean.getObject();
} catch (Exception ex) {
LOGGER.error("Unable to retrieve notification sender implementations", ex);
}
return senders;
}
private List<NotificationSender> createProxiedNotificationSendersAsSpringWillNotCreateProxyForThese(List<NotificationSender> notificationSenders) {
List<NotificationSender> proxyNotificationSenders = new ArrayList<>();
for (NotificationSender sender : notificationSenders) {
proxyNotificationSenders.add(createAspectJProxy(sender));
}
return proxyNotificationSenders;
}
private NotificationSender createAspectJProxy(NotificationSender notificationSender) {
AspectJProxyFactory aspectJProxyFactory = new AspectJProxyFactory(notificationSender);
aspectJProxyFactory.addAspect(notificationPerformanceLogger);
return aspectJProxyFactory.getProxy();
}