由于您仍然没有提供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() 中不再有杂乱的样板文件
- 添加了用于演示目的的 main 方法
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 通用的已实现接口?然后切入点看起来会有所不同。
- 您是只想拦截方法
listUsers() 还是还想拦截其他方法?由于您没有显示更多代码,因此除了您之外没有人知道。切入点也会因您的回答而有所不同。
- 您真的想手动完成这一切,还是听从其他用户的建议并使用板载 Spring 工具来管理您的事务?我对Spring一无所知,所以我不能告诉你。我只是为您提供与方面相关的问题的答案。