使用 Spring(AOP?)实现 Java 接口
Implements a Java Interface using Spring (AOP?)
我有几个简单的 getter 和 setter 接口以及一些其他方法来从文件系统读取和写入。
直接使用 Java 代码,我可以编写一个 "invocation handler" 并用它来实例化所有这些接口的对象(我没有尝试过,但我认为它可以完成)。
我想知道是否可以使用 Spring 来做同样的事情。
下面的代码实现了给定的接口。如您所见,相同的调用处理程序可用于任何接口。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class AOPTester {
public static void main(String[] args) {
InvocationHandler handler = new MyInvocationHandler();
AnyInterface proxy = (AnyInterface) Proxy.newProxyInstance(
AnyInterface.class.getClassLoader(),
new Class[] { AnyInterface.class },
handler);
proxy.sayHello();
}
}
interface AnyInterface {
public void sayHello();
}
class MyInvocationHandler implements InvocationHandler{
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("Hello!");
return null;
}
}
以下配置应该适合您(我使用了您的 类 但我将它们移到了不同的包中只是为了使代码更具可读性)。
我使用 spring 上下文对您使用的工厂方法 newProxyInstance() 执行相同的调用。
<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.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<bean id="pojoInvocationHandler" class="com.someco.PojoInvocationHandler"></bean>
<bean id="AnyInterfaceClass" class="java.lang.Class" factory-method="forName">
<constructor-arg value="com.someco.AnyInterface"/>
</bean>
<bean id="anyInterface" class="java.lang.reflect.Proxy" factory-method="newProxyInstance">
<constructor-arg>
<bean
factory-bean="AnyInterfaceClass"
factory-method="getClassLoader" />
</constructor-arg>
<constructor-arg>
<list>
<ref bean="AnyInterfaceClass" />
</list>
</constructor-arg>
<constructor-arg ref="pojoInvocationHandler"/>
</bean>
</beans>
代理测试器:
package com.someco;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.someco.AnyInterface;
public class ProxyTester {
public static void main(String[] args) {
ApplicationContext contex = new ClassPathXmlApplicationContext("application-context.xml");
AnyInterface tester = (AnyInterface) contex.getBean("anyInterface");
tester.sayHello();
/* Implemented with the previous code */
// callProxy();
}
/**
* @deprecated
* explanation of why function was deprecated, if possible include what
* should be used.
*/
@Deprecated
public static void callProxy() {
InvocationHandler handler = new PojoInvocationHandler();
AnyInterface proxy = (AnyInterface) Proxy.newProxyInstance(
AnyInterface.class.getClassLoader(),
new Class[] { AnyInterface.class },
handler);
proxy.sayHello();
}
}
PojoInvocationHandler:
package com.someco;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class PojoInvocationHandler implements InvocationHandler{
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("Hello!");
return null;
}
}
任意接口:
package com.someco;
public interface AnyInterface {
public void sayHello();
}
基本pom.xml:
<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.someco</groupId>
<artifactId>proxy-tester</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>main</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>3.0.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</project>
实际上有一种使用 ProxyFactoryBean Spring 的简洁方法。
在下面的示例中,这个 class 是在没有目标 bean 的情况下初始化的。
创建的对象没有任何转发请求的目标,但它可以像 Java.
中的任何其他代理一样实现任何接口
当然,如果您尝试在传递给 MethodInterceptor 的 invoke 方法的调用对象上调用 proceed 方法,您将得到 NullPointerException。
更好的应用-context.xml:
<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.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<bean id="goodbyeMethodInterceptor" class="com.someco.GoodbyeMethodInterceptor" />
<bean name="goodbyeProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interfaces">
<list>
<value>com.someco.AnyInterface</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>goodbyeMethodInterceptor</value>
</list>
</property>
</bean>
</beans>
再见方法拦截器:
package com.someco;
import org.aopalliance.intercept.MethodInvocation;
public class GoodbyeMethodInterceptor implements org.aopalliance.intercept.MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Goodbye");
return null;
}
}
代理测试器:
package com.someco;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.someco.AnyInterface;
public class ProxyTester {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("better-application-context.xml");
AnyInterface tester = (AnyInterface) context.getBean("goodbyeProxy");
tester.sayHello();
}
}
任何接口:
package com.someco;
public interface AnyInterface {
public void sayHello();
}
基本pom.xml:
<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.someco</groupId>
<artifactId>proxy-tester</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>main</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>3.0.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</project>
我有几个简单的 getter 和 setter 接口以及一些其他方法来从文件系统读取和写入。 直接使用 Java 代码,我可以编写一个 "invocation handler" 并用它来实例化所有这些接口的对象(我没有尝试过,但我认为它可以完成)。
我想知道是否可以使用 Spring 来做同样的事情。
下面的代码实现了给定的接口。如您所见,相同的调用处理程序可用于任何接口。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class AOPTester {
public static void main(String[] args) {
InvocationHandler handler = new MyInvocationHandler();
AnyInterface proxy = (AnyInterface) Proxy.newProxyInstance(
AnyInterface.class.getClassLoader(),
new Class[] { AnyInterface.class },
handler);
proxy.sayHello();
}
}
interface AnyInterface {
public void sayHello();
}
class MyInvocationHandler implements InvocationHandler{
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("Hello!");
return null;
}
}
以下配置应该适合您(我使用了您的 类 但我将它们移到了不同的包中只是为了使代码更具可读性)。 我使用 spring 上下文对您使用的工厂方法 newProxyInstance() 执行相同的调用。
<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.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<bean id="pojoInvocationHandler" class="com.someco.PojoInvocationHandler"></bean>
<bean id="AnyInterfaceClass" class="java.lang.Class" factory-method="forName">
<constructor-arg value="com.someco.AnyInterface"/>
</bean>
<bean id="anyInterface" class="java.lang.reflect.Proxy" factory-method="newProxyInstance">
<constructor-arg>
<bean
factory-bean="AnyInterfaceClass"
factory-method="getClassLoader" />
</constructor-arg>
<constructor-arg>
<list>
<ref bean="AnyInterfaceClass" />
</list>
</constructor-arg>
<constructor-arg ref="pojoInvocationHandler"/>
</bean>
</beans>
代理测试器:
package com.someco;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.someco.AnyInterface;
public class ProxyTester {
public static void main(String[] args) {
ApplicationContext contex = new ClassPathXmlApplicationContext("application-context.xml");
AnyInterface tester = (AnyInterface) contex.getBean("anyInterface");
tester.sayHello();
/* Implemented with the previous code */
// callProxy();
}
/**
* @deprecated
* explanation of why function was deprecated, if possible include what
* should be used.
*/
@Deprecated
public static void callProxy() {
InvocationHandler handler = new PojoInvocationHandler();
AnyInterface proxy = (AnyInterface) Proxy.newProxyInstance(
AnyInterface.class.getClassLoader(),
new Class[] { AnyInterface.class },
handler);
proxy.sayHello();
}
}
PojoInvocationHandler:
package com.someco;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class PojoInvocationHandler implements InvocationHandler{
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("Hello!");
return null;
}
}
任意接口:
package com.someco;
public interface AnyInterface {
public void sayHello();
}
基本pom.xml:
<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.someco</groupId>
<artifactId>proxy-tester</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>main</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>3.0.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</project>
实际上有一种使用 ProxyFactoryBean Spring 的简洁方法。 在下面的示例中,这个 class 是在没有目标 bean 的情况下初始化的。 创建的对象没有任何转发请求的目标,但它可以像 Java.
中的任何其他代理一样实现任何接口当然,如果您尝试在传递给 MethodInterceptor 的 invoke 方法的调用对象上调用 proceed 方法,您将得到 NullPointerException。
更好的应用-context.xml:
<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.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<bean id="goodbyeMethodInterceptor" class="com.someco.GoodbyeMethodInterceptor" />
<bean name="goodbyeProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interfaces">
<list>
<value>com.someco.AnyInterface</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>goodbyeMethodInterceptor</value>
</list>
</property>
</bean>
</beans>
再见方法拦截器:
package com.someco;
import org.aopalliance.intercept.MethodInvocation;
public class GoodbyeMethodInterceptor implements org.aopalliance.intercept.MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Goodbye");
return null;
}
}
代理测试器:
package com.someco;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.someco.AnyInterface;
public class ProxyTester {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("better-application-context.xml");
AnyInterface tester = (AnyInterface) context.getBean("goodbyeProxy");
tester.sayHello();
}
}
任何接口:
package com.someco;
public interface AnyInterface {
public void sayHello();
}
基本pom.xml:
<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.someco</groupId>
<artifactId>proxy-tester</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>main</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>3.0.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</project>