使用Cglib的Spring Boot App会抛出InvocationTargetException

时间:2018-05-16 13:16:59

标签: java spring spring-boot cglib

我正在尝试使用延迟加载我的实体来实现Repository模式(我不能使用JPA,因为它是一个遗留数据库模型)。为了延迟加载实体,我使用cglib MethodInterceptor来拦截实体的getter方法,并动态地水合相应的属性。例如,在Airport实体的情况下,只有在调用相应的getter时,我才会延迟加载Terminals属性。整件事打包为弹簧启动应用程序。

存储库实现由:

给出
@Component
public class AirportsRepository implements Repository<Airport, String> {

    @Autowired
    private AirportMapper airportMapper;
    @Autowired
    private TerminalMapper terminalMapper;

    private List<AirportInterceptor> airportInterceptors = new ArrayList<>();

    @Override
    public Airport get(String id) {
        Airport airport = airportMapper.findById(id);
        if(airport != null){
            AirportInterceptor airportInterceptor = new AirportInterceptor(airport, terminalMapper);
            airport = (Airport) Enhancer.create(Airport.class,airportInterceptor);
            this.airportInterceptors.add(airportInterceptor);
            return airport;
        }
        return airport;
    }

    @Override
    public void add(Airport entity) {
         //
    }
    @Override
    public void remove(Airport entity) {
         //
    }

    @Override
    public void saveChanges(){
        //

    }

}

public class Airport
{
    // ...
}

方法拦截器:

class AirportInterceptor implements MethodInterceptor {
    private TerminalMapper terminalMapper;
    private Airport airport;

    public AirportInterceptor(Airport airport, TerminalMapper terminalMapper){
        this.airport = airport;
        this.terminalMapper = terminalMapper;
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        if(method.getName().equals("getTerminals") && method.invoke(obj, args) == null){
            // Hydrate terminals
            List<Terminal> terminals = terminalMapper.findByAirportCode(airport.getId());
            airport.setTerminals(terminals);
        }
        return method.invoke(obj, args);
    }

    public void saveChanges(){
        //airportMapper.update(this.airport);
    }

}

但是,当我调用Enhancer.create()时,我遇到了存储库代码的问题,这会引发关于方法toString()的神秘异常:

Method threw 'java.lang.reflect.InvocationTargetException' exception. Cannot evaluate com.apm.airportservice.entities.Airport$$EnhancerByCGLIB$$d0daae41.toString()

1 个答案:

答案 0 :(得分:0)

如何配置Enhancer类?

您可能需要在班级添加此注释:

@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)