Answer the question
In order to leave comments, you need to log in
Can you advise Best-practice on the implementation of end-to-end logic for detecting changes in an object?
In the book "Spring 3 for Professionals" I saw an example of end-to-end logic "Object modification detection using injections". Slightly changed the code indicated there:
interface
public interface IsModified {
public boolean isModified();
}
public class IsModifiedMixin extends DelegatingIntroductionInterceptor implements IsModified {
private boolean isModified = false;
private Map<Method, Method> methodCache = new HashMap<Method, Method>();
public boolean isModified() {
return isModified;
}
public Object invoke(MethodInvocation invocation) throws Throwable {
if (!isModified) {
if ((invocation.getMethod().getName().startsWith("set"))
&& (invocation.getArguments().length == 1)) {
// Вызвать соответствующий метод get, чтобы посмотреть,
// изменилось ли значение.
Method getter = getGetter(invocation.getMethod());
if (getter != null) {
// Для методов, предназначенных только для записи,
// проверка модификации не важна.
Object newVal = invocation.getArguments()[0];
Object oldVal = getter.invoke(invocation.getThis(), null);
if ((newVal == null) && (oldVal == null)) {
isModified = false;
} else if ((newVal == null) && (oldVal != null)) {
isModified = true;
} else if ((newVal != null) && (oldVal == null)) {
isModified = true;
} else {
isModified = (!newVal.equals(oldVal));
}
}
}
}
return super.invoke(invocation);
}
private Method getGetter(Method setter) {
Method getter = null;
// Попытка извлечения из кеша.
getter = (Method) methodCache.get(setter);
if (getter != null) {
return getter;
}
String getterName = setter.getName().replaceFirst("set", "get");
try {
getter = setter.getDeclaringClass().getMethod(getterName, null);
// Метод извлечения из кеша.
synchronized (methodCache) {
methodCache.put(setter, getter);
}
return getter;
} catch (NoSuchMethodException ex) {
// Должен быть только для записи.
return null;
}
}
}
public class IsModifiedAdvisor extends DefaultPointcutAdvisor {
public IsModifiedAdvisor() {
super(new IsModifiedMixin());
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="modifiedAdvisor"
class="ru.its360.system.modifiedmixin.advisor.IsModifiedAdvisor">
<property name="pointcut">
<bean class="org.springframework.aop.aspectj.AspectJExpressionPointcut">
<property name="expression" value="execution(* ru.its360.development360..domain.model..*(..))"/>
</bean>
</property>
</bean>
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
</beans>
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'creditProgramManager': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.its360.document.ticket.service.api.ticket.category.ITicketCategoryManager ru.its360.development.development360.credits.creditprogram.service.application.CreditProgramManager.ticketCategoryManager; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ticketCategoryManager': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.its360.leasing360.workflow.IWorkFlowManager ru.its360.security.accesslayer.service.application.SecurityAbstractManager.flowManager; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'workFlowManager': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.its360.development.development360.tenders.tender.service.api.ITenderManager ru.its360.development360.workflow.workflow.service.application.WorkFlowManager.tenderManager; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tenderManager': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.its360.development.development360.tenders.developmentcontract.service.api.IDevelopmentContractManager ru.its360.development.development360.tenders.tender.service.application.TenderManager.developmentContractManager; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'developmentContractManager': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.its360.development.development360.tenders.paymentprofile.service.api.IPaymentProfileManager ru.its360.development.development360.tenders.developmentcontract.service.application.DevelopmentContractManager.paymentProfileManager; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'paymentProfileManager': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.its360.development.development360.tenders.paymentprofile.service.calc.api.IPaymentProfileCalculatorFactory ru.its360.development.development360.tenders.paymentprofile.service.application.PaymentProfileManager.paymentProfileCalculatorFactory; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'paymentProfileCalculatorFactory': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.its360.development.development360.tenders.paymentprofile.service.calc.api.IDDUFullOfShareWithoutCreditCalculator ru.its360.development.development360.tenders.paymentprofile.service.calc.application.PaymentProfileCalculatorFactory.dduFullOfShareWithoutCreditCalculator; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'DDUFullOfShareWithoutCreditCalculator': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: protected ru.its360.development.development360.buildings.section.service.api.IRealtyObjectManager ru.its360.development.development360.tenders.paymentprofile.service.calc.application.AbstractPaymentProfileCalculator.realtyObjectManager; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'realtyObjectManager': Bean with name 'realtyObjectManager' has been injected into other beans [statusRealtyObjectManager] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question