Поскольку вы до сих пор не предоставили MCVE или хотя бы еще некоторый (и более реалистичный) пример кода, я могу только строить догадки и давать схематический ответ.
Кстати, я использую AspectJ, а не Spring AOP, но он должен работать там же.
Пустые классы для компиляции примера кода:
package ua.com.alistratenko.dao;
public class User {
String name;
public User(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [name=" + name + "]";
}
}
package ua.com.alistratenko.dao;
import java.util.ArrayList;
import java.util.List;
public class QueryResult {
public List<User> list() {
List<User> users = new ArrayList<>();
users.add(new User("jane"));
users.add(new User("joe"));
return users;
}
}
package ua.com.alistratenko.dao;
public class Session {
public QueryResult createQuery(String string) {
return new QueryResult();
}
public void close() {}
}
package ua.com.alistratenko.dao;
public class SessionFactory {
public Session openSession() {
return new Session();
}
}
Класс применения:
Что я изменил?
- В Spring вы будете использовать
@Autowired
вместо того, чтобы создавать фабрику сессий самостоятельно. Я просто сделал это, чтобы иметь возможность запускать мой пример кода без Spring.
- Добавлены некоторые установщики / получатели для аспекта, чтобы иметь возможность доступа к фабрике сеансов, а также к самому сеансу
- Удалено
createSession()
(код перенесен в аспект, см. Ниже)
- Нет больше беспорядка в шаблоне
listUsers()
- Добавлен основной метод для демонстрационных целей
package ua.com.alistratenko.dao;
import java.util.List;
public class UserDaoImp {
private SessionFactory sessionFactory = new SessionFactory();
private Session session;
public SessionFactory getSessionFactory() { return sessionFactory; }
public Session getSession() { return session; }
public void setSession(Session session) { this.session = session; }
public List<User> listUsers() {
return session.createQuery("from User").list();
}
public static void main(String[] args) {
new UserDaoImp().listUsers();
}
}
Формат:
Чтобы сделать что-то до + после перехваченного вызова метода, используйте @Around
.
package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
//import org.springframework.stereotype.Component;
import ua.com.alistratenko.dao.UserDaoImp;
//@Component
@Aspect
public class DaoSessionLifeCycle {
@Around("execution(public * listUsers(..)) && target(dao)")
public Object openSession(ProceedingJoinPoint thisJoinPoint, UserDaoImp dao) throws Throwable {
try {
System.out.println("Creating session");
dao.setSession(dao.getSessionFactory().openSession());
System.out.println("Calling " + thisJoinPoint.getSignature());
return thisJoinPoint.proceed();
}
finally {
try {
System.out.println("Closing session");
dao.getSession().close();
}
catch (Exception e) {}
}
}
}
Журнал консоли:
Creating session
Calling List ua.com.alistratenko.dao.UserDaoImp.listUsers()
Closing session
Теперь есть несколько открытых вопросов:
- Вы хотите обрабатывать только этот один класс или, может быть, все подклассы базового класса или реализованный интерфейс, общий для всех ваших DAO? Тогда pointcut будет выглядеть иначе.
- Вы хотите перехватить только метод
listUsers()
или, может быть, другие методы? Поскольку вы не показали больше кода, никто, кроме вас, не может знать. Pointcut также будет выглядеть по-разному в зависимости от вашего ответа.
- Вы действительно хотите сделать все это вручную или, возможно, последуете советам других пользователей и используете встроенные инструменты Spring для управления своими транзакциями? Я понятия не имею о весне, поэтому не могу вам сказать. Я просто давал ответ на ваш вопрос, который был связан с аспектами.