编程时出错 Spring AOP+Hibernate

Error while programing Spring AOP+Hibernate

我正在阅读此处提供的示例:https://www.mkyong.com/spring/spring-aop-examples-advice,并尝试实现一个示例,使代码适应我之前的项目。我有一个单独的 Web 应用程序,它在数据库中保存给定人员的姓名和国家/地区,我想 "intercept" 执行更新或删除等操作。

我是整个 Spring+Hibernate 世界的新手,所以我不知道我的代码是否有误。因此,我将在此处留给您一些代码示例:

我的项目结构:

Package AOP

  • HijackAroundMethod.java

Package Controller

  • PersonController.java

Package DAO

  • PersonDAO.java

  • PersonDAOImpl.java

Package Model

  • Person.java

Package Service

  • PersonService.java

  • PersonServiceImpl.java

建议方法(见前面提到的页面):

public class HijackAroundMethod implements MethodInterceptor{

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {

        System.out.println("Method name: "+ invocation.getMethod().getName());
        System.out.println("Method arguments: " + Arrays.toString(invocation.getArguments()));
        System.out.println("Before executing operation");

        try{
            Object result = invocation.proceed();
            System.out.println("After executing method");
            return result;
        }catch(IllegalArgumentException e){
            System.out.println("Exception catched");
            throw e;
        }
    }

我的 DAO 示例 class(这里是我实现与 DB 持久性相关的功能的地方):

@Repository
public class PersonDAOImpl extends HibernateDaoSupport implements PersonDAO {

    private static final Logger logger = LoggerFactory.getLogger(PersonDAOImpl.class);

    @Autowired
    private SessionFactory sessionFactory;

    @Autowired
    public PersonDAOImpl(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }

    @Override
    @Transactional
    public void addPerson(Person p) {
        Session session = this.sessionFactory.getCurrentSession();
        session.persist(p);
        logger.info("Person saved successfully, Person Details="+p);
    }

    @Override
    @Transactional
    public void updatePerson(Person p) {
        Session session = this.sessionFactory.getCurrentSession();
        session.update(p);
        logger.info("Person updated successfully, Person Details="+p);
    }

这是我添加到我的 servlet-content.xml(我定义 beans 配置的地方):

<bean id="PersonDAOImpl" class="com.dacasals.raspertwo.dao.PersonDAOImpl"/>

<bean id="HijackAroundMethod" class="com.dacasals.raspertwo.aop.HijackAroundMethod"/>

<bean id="PersonDAOImplProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target" ref="PersonDAOImpl"/>
    <property name="interceptorNames">
        <list>
            <value>HijackAroundMethod</value>
        </list>
    </property>
</bean>

当我在我的服务器中 运行 执行此操作时(我将 STS 3.8.1 与 Tomcat 7 一起使用),我收到以下错误:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.dacasals.raspertwo.dao.PersonDAO] is defined: expected single matching bean but found 3: PersonDAOImpl,PersonDAOImplProxy,personDAOImpl
    org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:172)
    org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1106)
    org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1056)
    org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:566)
    org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:349)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1219)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:306)
    org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:207)
    org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1128)
    org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1056)
    org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:566)
    org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:349)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1219)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:306)
    org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:751)
    org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861)
    org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
    org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668)
    org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:634)
    org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:682)
    org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:553)
    org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494)
    org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
    javax.servlet.GenericServlet.init(GenericServlet.java:160)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
    org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    java.lang.Thread.run(Thread.java:745)

我一直在 Whosebug 中阅读一些问题,但我找不到任何与我相似的案例。

spring 配置有一些误解

当您将注释 @Repository 放在 class PersonDAOImpl spring 上时,通过使用自动扫描,创建一个名为 personDAOImpl[=59 的 bean =] 并且他的 bean 实现了接口 PersonDAO

那你就用配置文件吧。在此声明:

<bean id="PersonDAOImpl" class="com.dacasals.raspertwo.dao.PersonDAOImpl"/>

在这种情况下,spring 创建了一个名为 PersonDAOImpl 的新 bean,该 bean 实现了 PersonDAO,并且它的名称与前一个不同(第一个字符大写)

最后总是在你声明的配置文件中:

<bean id="PersonDAOImplProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target" ref="PersonDAOImpl"/>
    <property name="interceptorNames">
        <list>
            <value>HijackAroundMethod</value>
        </list>
    </property>
</bean>

这是一个新的 "proxied bean",它的最终 class 是 PersonDAOImpl,这个 bean 名称是 PersonDAOImplProxy。此 bean 还实现了 PersonDAO

此时您拥有三个不同的 bean,它们都实现了相同的接口。豆子是:

  1. personDAOImpl
  2. PersonDAOImpl
  3. PersonDAOImplProxy

当您尝试使用 @Autowired 将一个 bean 注入另一个 bean 时,您不能简单地使用此语法:

@Autowired
private PersonDAO myDao;

Spring 不知道应该注入 3 个 bean 中的哪一个。所以你必须告诉 spring 使用 3 个中的一个。这是通过使用 @Qualifier 注释来完成的。假设你想注入代理 bean,你应该使用这样的东西:

@Autowired
@Qualifier("PersonDAOImplProxy")
private PersonDAO myDao;

这样 spring 知道它必须注入一个实现接口的 bean PersonDAO 并且它知道你想使用代理 bean

无论如何我认为您只想使用其中一个 bean,因此您应该检查 spring 配置并优化它

我希望这是有用的

安杰洛

好吧,几天后我决定尝试另一种方法来在我的应用程序上使用方面,现在工作正常。

我读了书"Spring in action"第4版,我发现那里有很好的方面的例子。我没有使用 "Hijack" class,而是使用 @Pointcut、@After 和 @Before 等注解声明了一个新的 class。然后,我能够 "listen" 我的 class 执行的操作。

虽然我的目标是创建一种通用的方式来处理 "listen" 中的事件 Spring+Hibernate,这是一个好的开始。太糟糕了,我无法 运行 我之前访问过的网站提供的示例。感谢大家的指教,过段时间再请教