是否在Spring 4中优雅地处理了代理问题?

时间:2016-11-28 08:03:54

标签: java spring

我无法找到回答此问题的任何文件。

总结:

  • 我有一个实现接口的bean。
  • 我将proxy-target-class设置为false。
  • 我在Spring 3.2.17和4.3.3版本之间切换。
  • 当我使用Spring 3.2.17时,主类会抛出这个:

    java.lang.ClassCastException:com.sun.proxy。$ Proxy7无法强制转换为        com.package1.Camera             在com.package1.App.main(App.java:8)

    这就是我的预期。这是正确的行为,因为生成了JDK代理类。

  • 但是当我使用Spring 4.3.3时,不会抛出任何异常并且主类正常运行。

    生成了CGLIB代理类。但是,当我将proxy-target-class设置为false时,为什么会生成它?

以下是源文件:

App.java

<!DOCTYPE html>
<html>
<head>
<style>
table, th , td {
border: 1px solid grey;
border-collapse: collapse;
padding: 5px;
}
table tr:nth-child(odd) {
background-color: #f1f1f1;
}
table tr:nth-child(even) {
background-color: #ffffff;
}
</style>
<script src= “http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js”></script>
</head>
<body>

<div ng-app=”” ng-controller=”blogController”>

<table>
<tr><td>Manger Id</td><td>Manger Name</td></tr>
  <tr ng-repeat=”x in name”>
    <td>{{ x.m_id }}</td>

<td>{{ x.name }}</td>


  </tr>
</table>

</div>

<script>
function blogController($scope,$http) {
$http.get('http://localhost:3000/techgeek/v1/getEmployeeDetails')
.success(function(response) {
    $scope.names = response;
    console.log($scope.names);
});
}
</script>

</body>
</html>

ICamera.java

package com.package1;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Camera camera = (Camera) context.getBean("camera");
        camera.snap();
        context.close();
    }
}

Camera.java

package com.package1;
public interface ICamera {}

Logger.java

package com.package1;

import org.springframework.stereotype.Component;

@Component("camera")
public class Camera implements ICamera {
    public void snap() {
        System.out.println("SNAP!");
    }
}

的beans.xml

package com.package1;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class Logger {

    @Pointcut("execution(void com.package1.Camera.snap())")
    public void cameraSnap() {

    }

    @Before("cameraSnap()")
    public void beforeAdvice() {
        System.out.println("Before advice...");
    }

}

的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">


    <context:component-scan
        base-package="com.package1">
    </context:component-scan>

    <aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>

</beans>

2 个答案:

答案 0 :(得分:1)

当您设置proxy-target-class = false时,CGLIB代理仍会使用相同的公式JDK代理创建。 在Spring docs中,他们说:

  

Spring AOP使用JDK动态代理或CGLIB为给定目标对象创建代理。 (只要您有选择,JDK动态代理就是首选。)

     

如果要代理的目标对象实现至少一个接口,则将使用JDK动态代理。目标类型实现的所有接口都将被代理。如果目标对象没有实现任何接口,那么将创建一个CGLIB代理。

查看更多:Proxying mechanisms

答案 1 :(得分:0)

通过反复试验我得到了答案。

<强> App.java

package com.package1;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Object o = context.getBean("camera");
        System.out.println("class=" + o.getClass());
        Camera camera = (Camera) context.getBean("camera");
        camera.snap();
        context.close();
    }
}

proxy-target-class仍然默认为false。

但是现在,Spring 4足够聪明它将生成什么代理(JDK或CGLIB)。

  • 如果您有一个空接口,它将生成一个CGLIB代理。

<强> ICamera.java

package com.package1;
public interface ICamera {}
  • 否则,将生成JDK代理。

<强> ICamera.java

package com.package1;

public interface ICamera {
    void snap();
}

HTH。