如何利用Spring AOP在DAO类方法执行前调用createSession方法?
Got it, let's walk through how to use Spring AOP to eliminate that repetitive createSession() call in every DAO method. Plus, we'll fix a hidden thread safety issue in your current setup—because that's a gotcha you don't want to hit in production.
Step 1: Add Spring AOP Dependencies
First, make sure your project has the necessary AOP libraries. If you're using Maven, add these to your pom.xml (adjust versions to match your Spring release):
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> </dependency>
Step 2: Fix the Thread Safety Problem (Critical!)
Your current DAO uses an instance-level Session variable, which is dangerous. Spring DAOs are singletons, so multiple concurrent requests will share this non-thread-safe Hibernate Session. Let's fix this by using a ThreadLocal to store the session per request:
// BaseDao (have all your DAOs extend this) public abstract class BaseDao { @Autowired protected SessionFactory sessionFactory; private ThreadLocal<Session> sessionThreadLocal = new ThreadLocal<>(); protected void createSession() { sessionThreadLocal.set(sessionFactory.openSession()); } protected Session getSession() { return sessionThreadLocal.get(); } protected void closeSession() { Session session = sessionThreadLocal.get(); if (session != null && session.isOpen()) { session.close(); sessionThreadLocal.remove(); } } }
Now your UserDaoImpl can extend this base class:
@Repository public class UserDaoImpl extends BaseDao implements UserDao { @Override public List<User> listUsers() { // No more manual createSession() or close() calls soon! List<User> users = getSession().createQuery("from User").list(); return users; } }
Step 3: Create the AOP Aspect
This aspect will handle calling createSession() before your DAO methods run, and closeSession() after (to clean up):
import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect @Component public class DaoSessionManagementAspect { // Match all public methods in DAO classes (adjust the package to your setup) private static final String DAO_METHOD_POINTCUT = "execution(public * com.yourpackage.dao..*(..))"; @Before(DAO_METHOD_POINTCUT) public void beforeDaoMethod(BaseDao dao) { dao.createSession(); } @After(DAO_METHOD_POINTCUT) public void afterDaoMethod(BaseDao dao) { dao.closeSession(); } }
Pointcut Breakdown:
execution(public * com.yourpackage.dao..*(..)): This targets all public methods in any class undercom.yourpackage.dao(including subpackages). Tweak the package path to match your DAO location.- We're using
BaseDaoas the parameter type here because all your DAOs extend it—this ensures we can safely callcreateSession()andcloseSession().
Step 4: Enable Spring AOP
Tell Spring to scan for aspects and enable proxying. If you're using Java config:
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration @ComponentScan(basePackages = "com.yourpackage") @EnableAspectJAutoProxy public class AppConfig { // Your SessionFactory bean definition goes here }
If you're using XML config:
<aop:aspectj-autoproxy /> <context:component-scan base-package="com.yourpackage" />
Bonus: Consider a More Idiomatic Spring Approach
While this AOP solution works, Spring has built-in tools to handle Hibernate session management even better:
@TransactionalAnnotation: Mark your DAO (or service) methods with@Transactional, and Spring will automatically handle session opening, transaction boundaries, and session closing. Just make sure to configure aPlatformTransactionManagerfor Hibernate.HibernateTemplate: A legacy but still valid option that wraps Hibernate operations and manages sessions for you.
But if you need to stick with your custom session creation logic, the AOP approach above is solid and eliminates repetitive code.
内容的提问来源于stack exchange,提问作者Nikita

