Java 无法将特性应用于字符串类

Java 无法将特性应用于字符串类,java,spring,aspectj,aspect,Java,Spring,Aspectj,Aspect,我在试验AspectJ。我尝试在String类上应用aspect。我将Spring配置文件创建为: <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" xsi:schemaLocation="ht

我在试验
AspectJ
。我尝试在String类上应用aspect。我将Spring配置文件创建为:

<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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

    <!-- Enable @AspectJ annotation support -->
    <aop:aspectj-autoproxy />

    <!-- Employee manager -->
    <bean id="employeeManager" class="com.test.advice.EmployeeManager" />

    <!-- Logging Aspect -->
    <bean id="loggingAspect" class="com.test.advice.LoggingAspect" />

    <bean id="bean1" class="java.lang.String">
        <constructor-arg value="abx" />
    </bean>

</beans>
之后,创建了一个类,其中包含一个main方法,如:

package com.test.advice;

package com.test.advice;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AspectJAutoProxyTest
{
    public static void main(String[] args)
    {
        ApplicationContext context = new ClassPathXmlApplicationContext("Spring-Customer.xml");

        String pqr = (String) context.getBean("bean1");

        pqr.trim();

    }
}
在运行时,它应该向控制台输出“works”。但它没有说

Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy5 cannot be cast to java.lang.String
    at com.test.advice.AspectJAutoProxyTest.main(AspectJAutoProxyTest.java:13)

问题是什么?我们不能将代理应用于java.lang对象吗?请提供帮助。

要使用代理对象替换真实对象,代理对象必须是真实对象的子类
String
作为
final
,JVM不允许创建这样的子类


(请注意,spring有两种代理模式;一种创建实际的子类,另一种只实现所有公共接口。您可能正在使用后者,但如果更改为前者,您将在代理创建时看到异常)

使用代理对象替换真实对象,代理对象必须是真实对象的子类
String
作为
final
,JVM不允许创建这样的子类


(请注意,spring有两种代理模式;一种是创建实际的子类,另一种只是实现所有公共接口。您可能正在使用后者,但如果更改为前者,您将在代理创建时看到异常)

这只是问题的一小部分,而不是真正的答案。即使字符串不是最终的,它(a)也不是SpringBean,因此SpringAOP不会注意到它,(b)即使您切换到AspectJ以消除此限制,您也不能通过加载时编织来编织到JDK类中,因为这些类在编织代理启动之前已经加载。但是使用AspectJ,您至少可以使用
调用(*java.lang.String.*(..)
,从而在您自己的或加载时编织的第三方类中拦截调用站点。实际上,OP确实将字符串声明为Springbean:
.True。不过这并不重要,因为
执行(*java.lang.String.*(..)
是SpringAOP的禁区。是的,理论上它可以动态代理,如果它不是最终的。但这不会有帮助。你有什么证据证明这个切入点是“禁区”?问题中显示的异常表明SpringAOP已经决定代理bean,SpringAOP只代理匹配切入点的bean。(是的,我知道加载时编织不能修饰JDK类,但代理创建对于JDK类的SpringBean来说很好,只要它们不是最终的)感谢您挑战我的论点并让我再次思考。关于动态代理(即Spring AOP),您是对的。理论上,若字符串不是最终的,那个么它可以被代理为字符串的子类,并被转换回其父类。如果您运行上述程序,您甚至有一个工作代理,它还具有来自已实现接口的所有字符串方法
Serializable
CharSequence
Comparable
。也就是说,如果您执行
((CharSequence)appContext.getBean(“bean1”))。子序列(1,3)
,则方面将生效。所以“禁区”实际上只适用于AspectJ,这只是问题的一小部分,不是真正的答案。即使字符串不是最终的,它(a)也不是SpringBean,因此SpringAOP不会注意到它,(b)即使您切换到AspectJ以消除此限制,您也不能通过加载时编织来编织到JDK类中,因为这些类在编织代理启动之前已经加载。但是使用AspectJ,您至少可以使用
调用(*java.lang.String.*(..)
,从而在您自己的或加载时编织的第三方类中拦截调用站点。实际上,OP确实将字符串声明为Springbean:
.True。不过这并不重要,因为
执行(*java.lang.String.*(..)
是SpringAOP的禁区。是的,理论上它可以动态代理,如果它不是最终的。但这不会有帮助。你有什么证据证明这个切入点是“禁区”?问题中显示的异常表明SpringAOP已经决定代理bean,SpringAOP只代理匹配切入点的bean。(是的,我知道加载时编织不能修饰JDK类,但代理创建对于JDK类的SpringBean来说很好,只要它们不是最终的)感谢您挑战我的论点并让我再次思考。关于动态代理(即Spring AOP),您是对的。理论上,若字符串不是最终的,那个么它可以被代理为字符串的子类,并被转换回其父类。如果您运行上述程序,您甚至有一个工作代理,它还具有来自已实现接口的所有字符串方法
Serializable
CharSequence
Comparable
。也就是说,如果您执行
((CharSequence)appContext.getBean(“bean1”))。子序列(1,3)
,则方面将生效。所以在这种情况下,“禁区”实际上只适用于AspectJ。
Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy5 cannot be cast to java.lang.String
    at com.test.advice.AspectJAutoProxyTest.main(AspectJAutoProxyTest.java:13)