Java Spring将一个类的一个方法放在另一个之前

Java Spring将一个类的一个方法放在另一个之前,java,spring,hibernate,aop,Java,Spring,Hibernate,Aop,我有一个使用SpringCore、SpringMVC和Hibernate的应用程序。 有很多DAO类在每种方法中都会获得新的Hibernate会话 @Autowired private SessionFactory sessionFactory; private Session session; private void createSession() { session = sessionFactory.openSession(); } @Override publi

我有一个使用SpringCore、SpringMVC和Hibernate的应用程序。 有很多DAO类在每种方法中都会获得新的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;
}

除了@Bogdan所说的之外,看看
crudepository
JpaRepository
,它将为您节省大量时间。另外,在我看来,
@Aspect
类是用
@Component
注释的,而不是
@Configuration

,因为您仍然没有提供一个或至少更多(和更真实)的示例代码,我只能推测并提供一个示意性的答案

顺便说一句,我在这里使用的是AspectJ,而不是SpringAOP,但是在那里它应该以同样的方式工作

使示例代码编译的伪类:

包ua.com.alistratenko.dao;
公共类用户{
字符串名;
公共用户(字符串名称){
this.name=名称;
}
@凌驾
公共字符串toString(){
返回“User[name=“+name+”]”;
}
}
包ua.com.alistratenko.dao;
导入java.util.ArrayList;
导入java.util.List;
公共类查询结果{
公开名单(){
列表用户=新建ArrayList();
添加(新用户(“jane”);
添加(新用户(“joe”);
返回用户;
}
}
包ua.com.alistratenko.dao;
公开课{
公共查询Result createQuery(字符串){
返回新的QueryResult();
}
公共void close(){}
}
包ua.com.alistratenko.dao;
公共类会话工厂{
公开会话openSession(){
返回新会话();
}
}
应用程序类:

我改变了什么

  • 在春季,您将使用
    @Autowired
    ,而不是自己创建会话工厂。我这样做是为了能够在没有Spring的情况下运行示例代码
  • 为方面添加了一些setter/getter,以便能够访问会话工厂和会话本身
  • 删除了
    createSession()
    (代码迁移到aspect,见下文)
  • listUsers()中不再有杂乱无章的样板文件
  • 添加了用于演示的主方法
包ua.com.alistratenko.dao;
导入java.util.List;
公共类UserDaoImp{
私有SessionFactory SessionFactory=新SessionFactory();
非公开会议;
public SessionFactory getSessionFactory(){return SessionFactory;}
公共会话getSession(){return Session;}
public void setSession(会话){this.Session=Session;}
公共列表listUsers(){
return session.createQuery(“来自用户”).list();
}
公共静态void main(字符串[]args){
新UserDaoImp().listUsers();
}
}
方面:

为了在截获的方法调用之前+之后执行某些操作,请使用
@Around

package de.scrum\u master.aspect;
导入org.aspectj.lang.ProceedingJoinPoint;
导入org.aspectj.lang.annotation.Around;
导入org.aspectj.lang.annotation.Aspect;
//导入org.springframework.stereotype.Component;
导入ua.com.alistratenko.dao.UserDaoImp;
//@组成部分
@面貌
公共类DaoSessionLifeCycle{
@大约(“执行(公共*列表用户(..)&&target(dao)”)
公共对象openSession(ProceedingJoinPoint thisJoinPoint,UserDaoImp dao)抛出可丢弃的{
试一试{
System.out.println(“创建会话”);
setSession(dao.getSessionFactory().openSession());
System.out.println(“调用”+thisJoinPoint.getSignature());
返回此连接点。继续();
}
最后{
试一试{
System.out.println(“结束会议”);
dao.getSession().close();
}
捕获(例外e){}
}
}
}
控制台日志:

创建会话
调用列表ua.com.alistratenko.dao.UserDaoImp.listUsers()
闭幕会议
现在有几个悬而未决的问题:

  • 您是否只想处理这一个类,或者可能处理基类的所有子类,或者处理所有DAO通用的实现接口?那么切入点看起来就不一样了
  • 您是只想截取方法
    listUsers()
    还是还想截取其他方法?由于您没有显示更多的代码,除了您之外没有人知道。切入点也会根据您的答案而有所不同
  • 您真的想手动完成这些操作,还是按照其他用户的建议使用板载Spring工具来管理您的事务?我对春天一无所知,所以我不能告诉你。我只是提供了你的问题的答案,这是与方面有关的

使您的服务方法成为事务性的。Dao类将使用来自服务的事务。还可以阅读有关事务传播的内容。@BogdanLukiyanchuk,因此如果我使用此注释,我可以跳过创建/打开新会话。在这种情况下,我应该使用什么对象来处理DB?我的意思是,如果我不需要创建会话,也就是说我不需要这个类的实例,那么我还应该使用什么来处理DB?aspect无法工作的原因有很多:Spring配置、aspect代码、应用程序代码、包名、组件扫描设置。请提供一个完整的,而不仅仅是不连贯的片段。再现和分析你的问题比单纯的猜测更容易帮助你。欢迎来到SO@克里加克斯我没有说它不起作用。我说我不知道在使用方面调用同一类的另一个方法之前调用一个类方法的正确方法。因此,方面会被触发,并在预期的时间和地点打印“izi”?而您只发布正文的类实际上名为
ua.com.alistratenko.dao.UserDaoImp
,因为我只能从切入点间接推断出来?是的,Spring AOP方面需要是
@组件
,而纯AspectJ方面不需要。Update:我添加了虚拟类,使示例代码在没有Spring的情况下使用纯JavaSE+AspectJ编译
@Configuration
@Aspect
public class DaoSessionLifeCycle {

    @Before(value = "execution(* ua.com.alistratenko.dao.UserDaoImp.listUsers(..))")
    public void openSession(JoinPoint joinPoint){

        System.out.println("izi");
    }
}