복붙노트

[SPRING] 봄 부팅시 Aop 관련 문제

SPRING

봄 부팅시 Aop 관련 문제

내 응용 프로그램 클래스

import com.example.haha.Haha;
import com.example.hehe.Hehe;
import com.example.logging.Logging;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy
public class DemoApplication {

    public static void main(String[] args) throws InterruptedException {
        ApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);
        for(String name:ctx.getBeanDefinitionNames()){
            System.out.println(name);
        }
        Haha haha = (Haha)ctx.getBean("hh");
        haha.haha1();
        haha.haha2();
        return;
    }

}

Haha.java

package com.example.haha;

import org.springframework.stereotype.Component;

/**
 * Created by vamsi on 4/21/16.
 */
@Component("hh")
public class Haha {

    public Haha(){
    }


    public void haha1() throws InterruptedException {
        System.out.println("In method haha1");
        Thread.sleep(1000);
    }

    public void haha2() throws InterruptedException {
        System.out.println("In method haha2");
        Thread.sleep(2000);
    }

}

My Aspect 클래스

package com.example.logging;

import org.apache.commons.logging.Log;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

/**
 * Created by vamsi on 4/21/16.
 */
@Aspect
@Component
public class Logging {
    public Logging() {
    }

    @Pointcut("execution(public * *(..))")
    private void allPublicMethods(){}

    @Around("allPublicMethods()")
    public Object profile(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        System.out.println(pjp.getSignature() +"begins");
        Object output = pjp.proceed();
        System.out.println(pjp.getSignature()+"completed.");
        long elapsedTime = System.currentTimeMillis() - start;
        System.out.println("Method execution time: " + elapsedTime + " milliseconds.");
        return output;
    }
}

Pom.hml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.7</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

이것들은 내 스프링 부팅 응용 프로그램의 파일입니다. 내 응용 프로그램에서 AOP를 사용하여 모든 공용 메소드를보고 싶습니다. 내가 응용 프로그램을 실행할 때 다음 오류가 발생합니다.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.AutoConfigurationPackages': Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class org.springframework.boot.autoconfigure.AutoConfigurationPackages$BasePackages]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class org.springframework.boot.autoconfigure.AutoConfigurationPackages$BasePackages
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) ~[spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) ~[spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766) [spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361) [spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) [spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) [spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at com.example.DemoApplication.main(DemoApplication.java:18) [classes/:na]
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class org.springframework.boot.autoconfigure.AutoConfigurationPackages$BasePackages]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class org.springframework.boot.autoconfigure.AutoConfigurationPackages$BasePackages
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:213) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:468) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:349) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:298) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:422) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1583) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    ... 14 common frames omitted
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class org.springframework.boot.autoconfigure.AutoConfigurationPackages$BasePackages
    at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:457) ~[spring-core-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33) ~[spring-core-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) ~[spring-core-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$ClassLoaderAwareUndeclaredThrowableStrategy.generate(CglibAopProxy.java:990) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:231) ~[spring-core-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:378) ~[spring-core-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:318) ~[spring-core-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:55) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:203) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    ... 21 common frames omitted

해결법

  1. ==============================

    1.귀하의 Pointcut은 매우 일반적입니다 :

    귀하의 Pointcut은 매우 일반적입니다 :

    @Pointcut("execution(public * *(..))")
    

    그것은 classpath에있는 모든 클래스의 사용 가능한 모든 public 메소드를 조언 할 것입니다. 아쉽게도 Spring AOP는 classpath에 존재하는 클래스들에 대해 필요한 프록시를 만들 수 없다 (왜냐하면 그들은 어떤 인터페이스도 구현하지 않고 최종적이기 때문에). 따라서 오류가 발생한다 :

    pointcut을 클래스에 대한 조언으로 제한한다면, 괜찮을 것입니다!

  2. ==============================

    2.allPublicMethods pointcut이 너무 넓습니다. 그것은 모든 클래스의 모든 public 메소드에 적용됩니다. 일치하는 클래스는 org.springframework.boot.autoconfigure.AutoConfigurationPackages $ BasePackages입니다. 조언이 적용되는 것을 막는 final로 선언되었습니다.

    allPublicMethods pointcut이 너무 넓습니다. 그것은 모든 클래스의 모든 public 메소드에 적용됩니다. 일치하는 클래스는 org.springframework.boot.autoconfigure.AutoConfigurationPackages $ BasePackages입니다. 조언이 적용되는 것을 막는 final로 선언되었습니다.

    예를 들어 자신의 com.example 패키지에있는 코드에만 적용하여 pointcut의 범위를 좁혀 야합니다.

    @Pointcut("execution(public * com.example..*(..))")
    
  3. from https://stackoverflow.com/questions/36775611/problems-with-aop-in-spring-boot by cc-by-sa and MIT license