Предложения о том, как создать средство изменения на SlingModel, чтобы включить сохранение в JCR
В настоящее время мы пытаемся реализовать расширение для SlingModels, чтобы позволить слинг-модели быть сохраненной непосредственно в JCR.
В нашей стратегии 2 исходных условия: 1. Новый объект, который должен быть сохранен. 2. Объект, который был извлечен из JCR, изменен и затем должен быть снова сохранен.
Для ситуации 1 мы используем отражение, чтобы исследовать объект, создать новый узел для модели, вставить свойства для любой из найденных примитивных переменных и рекурсивно использовать тот же подход постоянства для любых сложных объектов модели, найденных как переменные и коллекции.
Мой вопрос о наилучшем подходе относится к ситуации 2. Если мы извлечем объект из хранилища, мы не можем быть уверены, что узел не будет синхронно изменен в это время. Таким образом, мы хотели бы реализовать наблюдатель изменений в SlingModel, который ведет журнал транзакций о любых внесенных изменениях. Затем транзакции можно использовать для установки соответствующих свойств при повторном сохранении объекта в JCR.
Я рассмотрел использование шаблона наблюдателя, но это означало бы, что нам нужно было бы реализовать функцию в сеттере для каждой модели SlingModel, которая вообще не идеальна, поскольку от разработчика требуется не забывать добавлять код и делать это правильно.
В идеале я хотел бы реализовать что-то вроде перехватчика непосредственно в переменной или, если это невозможно, в самом установщике, и поручить каждой модели затем использовать метод получения / установки для каждой переменной. Мы можем настроить инструменты сканирования кода, чтобы заставить разработчиков внедрять методы получения / установки.
Каков был бы лучший способ приблизиться к наблюдателю изменений здесь?
1 ответ
import java.util.List;
public class Teacher {
private String userName;
private String cource;
private List<Student> students;
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getCource() {
return cource;
}
public void setCource(String cource) {
this.cource = cource;
}
}
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class ClassFacadeCglib implements MethodInterceptor{
private Object target;
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// callback method
enhancer.setCallback(this);
// create proxy object
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
if(method.getName().startsWith("set")){
System.out.println(method.getName()+" start");
proxy.invokeSuper(obj, args);
System.out.println(method.getName()+" end..");
}
if(method.getName().startsWith("get")){
System.out.println(method.getName()+" start");
proxy.invokeSuper(obj, args);
System.out.println(method.getName()+" end");
}
return null;
}
}
public class Main {
public static void main(String[] args) {
ClassFacadeCglib cglib=new ClassFacadeCglib();
Teacher teacher=(Teacher)cglib.getInstance(new Teacher());
teacher.setCource("Math");
teacher.getUserName();
}
}
Замечания:
Для работы требуется cglib-full-2.0.2.jar. см. https://repo1.maven.org/maven2/cglib/cglib-full/2.0.2/