Spring AOP 一个方法一个 class 在另一个之前
Spring AOP one method of a class before another
我有一个使用 Spring Core、Spring MVC、Hibernate 的应用程序。
有很多 DAO classes 在像这样的每个方法中获得新的 Hibernate 会话
@Autowired
private SessionFactory sessionFactory;
private Session session;
private void createSession() {
session = sessionFactory.openSession();
}
@Override
public List<User> listUsers() {
createSession();
List users;
users = session.createQuery("from User").list();
session.close();
return users;
}
我想使用 AOP 在那些 class 方法之前执行 createSession 方法,但不知道该怎么做。
我所做的就是这方面
@Configuration
@Aspect
public class DaoSessionLifeCycle {
@Before(value = "execution(* ua.com.alistratenko.dao.UserDaoImp.listUsers(..))")
public void openSession(JoinPoint joinPoint){
System.out.println("izi");
}
}
除了@Bogdan 说的,看看CrudRepository
或JpaRepository
,会节省你很多时间。另外,在我看来,@Aspect
类 被注释为 @Component
而不是 @Configuration
.
因为你仍然没有提供MCVE或者至少一些更多(更现实)的示例代码,我只能推测并提供一个示意性的答案。
顺便说一句,我在这里使用的是 AspectJ 而不是 Spring AOP,但它应该以相同的方式工作。
Dummy classes 使示例代码编译:
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();
}
}
申请class:
我改变了什么?
- 在 Spring 中,您将使用
@Autowired
而不是自己创建会话工厂。我这样做是为了能够在没有 Spring. 的情况下 运行 我的示例代码
- 为能够访问会话工厂以及会话本身的方面添加了一些 setters/getters
- 删除
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
现在有几个悬而未决的问题:
- 您只想处理这个 class 还是一个基础 class 的所有子 class 或所有 DAO 通用的已实现接口?那么切入点看起来会有所不同。
- 您只想拦截方法
listUsers()
还是其他方法?由于您没有显示更多代码,因此除了您之外没有人知道。根据您的回答,切入点也会有所不同。
- 您真的想全部手动完成,还是听从其他用户的建议并使用机载 Spring 工具来管理您的交易?我不知道 Spring,所以我不能告诉你。我只是为您的问题提供了与方面相关的答案。
我有一个使用 Spring Core、Spring MVC、Hibernate 的应用程序。 有很多 DAO classes 在像这样的每个方法中获得新的 Hibernate 会话
@Autowired
private SessionFactory sessionFactory;
private Session session;
private void createSession() {
session = sessionFactory.openSession();
}
@Override
public List<User> listUsers() {
createSession();
List users;
users = session.createQuery("from User").list();
session.close();
return users;
}
我想使用 AOP 在那些 class 方法之前执行 createSession 方法,但不知道该怎么做。
我所做的就是这方面
@Configuration
@Aspect
public class DaoSessionLifeCycle {
@Before(value = "execution(* ua.com.alistratenko.dao.UserDaoImp.listUsers(..))")
public void openSession(JoinPoint joinPoint){
System.out.println("izi");
}
}
除了@Bogdan 说的,看看CrudRepository
或JpaRepository
,会节省你很多时间。另外,在我看来,@Aspect
类 被注释为 @Component
而不是 @Configuration
.
因为你仍然没有提供MCVE或者至少一些更多(更现实)的示例代码,我只能推测并提供一个示意性的答案。
顺便说一句,我在这里使用的是 AspectJ 而不是 Spring AOP,但它应该以相同的方式工作。
Dummy classes 使示例代码编译:
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();
}
}
申请class:
我改变了什么?
- 在 Spring 中,您将使用
@Autowired
而不是自己创建会话工厂。我这样做是为了能够在没有 Spring. 的情况下 运行 我的示例代码
- 为能够访问会话工厂以及会话本身的方面添加了一些 setters/getters
- 删除
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
现在有几个悬而未决的问题:
- 您只想处理这个 class 还是一个基础 class 的所有子 class 或所有 DAO 通用的已实现接口?那么切入点看起来会有所不同。
- 您只想拦截方法
listUsers()
还是其他方法?由于您没有显示更多代码,因此除了您之外没有人知道。根据您的回答,切入点也会有所不同。 - 您真的想全部手动完成,还是听从其他用户的建议并使用机载 Spring 工具来管理您的交易?我不知道 Spring,所以我不能告诉你。我只是为您的问题提供了与方面相关的答案。