我在网上搜索了很长时间。但没用。请帮助或尝试提供一些如何实现此目的的想法
在我的客户端,我可以使用我的Real Object获取我的方法的注释,但不能使用代理对象。
我曾经认为这是因为我自己的Annotation上缺少Retention Annotation。但它不起作用。这是代码:
注释:
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {}
接口
public interface UserDao {
void save();
void update();
}
实施
public class UserDaoImpl implements UserDao{
@Override
@MyAnnotation
public void save() {
System.out.println("save");
}
@Override
public void update() {
System.out.println("update");
}
}
客户端+驱动程序应用程序:
public class Client {
public static void main(String[] args) {
final UserDaoImpl dao = new UserDaoImpl();
Method[] methods = dao.getClass().getMethods();
for (Method m : methods){
if(m.getAnnotation(MyAnnotation.class) != null)
System.out.println("save method is enhanced");
}
UserDao proxy = (UserDao) Proxy.newProxyInstance(
dao.getClass().getClassLoader(),
dao.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
obj = dao;
if(method.getAnnotation(MyAnnotation.class) != null)
System.out.println("save method is enhanced2");
Object result = method.invoke(obj, args);
return result;
}
}
);
proxy.save();
System.out.println("-----------");
proxy.update();
}
}
答案 0 :(得分:1)
动态代理直接实现给定的接口,它不会像你想象的那样扩展实现类。我修复了你的非编译代码,添加了一些日志输出并将所有类移到我的一个包中,因为Java编译器不喜欢默认包。
驱动程序应用程序(已更新):
package de.scrum_master.so;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
final UserDaoImpl dao = new UserDaoImpl();
Method[] methods = dao.getClass().getMethods();
for (Method method : methods) {
if (method.getAnnotation(MyAnnotation.class) != null) {
System.out.println(method + " -> " + method.getDeclaringClass());
System.out.println("impl method is enhanced");
}
}
System.out.println("-----------");
UserDao proxy = (UserDao) Proxy.newProxyInstance(
dao.getClass().getClassLoader(),
dao.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
obj = dao;
System.out.println(method + " -> " + method.getDeclaringClass());
if (method.getAnnotation(MyAnnotation.class) != null)
System.out.println("proxy method is enhanced");
Object result = method.invoke(obj, args);
return result;
}
});
proxy.save();
System.out.println("-----------");
proxy.update();
}
}
控制台日志:
public void de.scrum_master.so.UserDaoImpl.save() -> class de.scrum_master.so.UserDaoImpl
impl method is enhanced
-----------
public abstract void de.scrum_master.so.UserDao.save() -> interface de.scrum_master.so.UserDao
save
-----------
public abstract void de.scrum_master.so.UserDao.update() -> interface de.scrum_master.so.UserDao
update
您可以在此处查看UserDaoImpl
与动态UserDao
代理之间的区别。
我不确定您为什么用spring
和aop
标记此问题,因为在您的示例代码中没有AOP而没有Spring,但我想您想要使用Spring AOP,它也基于动态代理。在那里,您可以选择强制执行接口的组件也将创建为CGLIB代理,即代理直接扩展其基类。也许它有效,但我不确定CGLIB代理如何工作。如果它们将覆盖每个方法,则会应用JVM限制:方法注释永远不会被重写方法继承。
非常适合您的技术问题。但你真正想要实现的目标是什么?这是许多人在这里犯的错误:他们没有描述他们想要实现的目标,但已经考虑到了可能不合适的技术解决方案。这样他们就会错过解决问题的其他选择。通常,应用程序设计基于其错误的假设存在缺陷,如果他们不太注重解决方案偏差,则可以轻松修复。也许如果这对您没有帮助,您可以创建一个新问题,将其链接到此问题,其中显示您的Spring AOP问题并描述您想要实现的目标。
更新:如果要从代理的调用处理程序访问原始(“真实”)对象,可以这样做:
改进了驱动程序应用程序:
package de.scrum_master.so;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
final UserDaoImpl dao = new UserDaoImpl();
Method[] methods = dao.getClass().getMethods();
for (Method method : methods) {
if (method.getAnnotation(MyAnnotation.class) != null) {
System.out.println(method + " -> " + method.getDeclaringClass());
System.out.println("impl method is enhanced");
}
}
System.out.println("-----------");
UserDao proxy = (UserDao) Proxy.newProxyInstance(
dao.getClass().getClassLoader(),
dao.getClass().getInterfaces(),
new MyInvocationHandler(dao)
);
proxy.save();
System.out.println("-----------");
proxy.update();
}
private static class MyInvocationHandler implements InvocationHandler {
private Object realObject;
public MyInvocationHandler(Object realObject) {
this.realObject = realObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method + " -> " + method.getDeclaringClass());
if (method.getAnnotation(MyAnnotation.class) != null)
System.out.println("proxy method is enhanced");
if (realObject.getClass().getMethod(method.getName(), method.getParameterTypes()).getAnnotation(MyAnnotation.class) != null)
System.out.println("real object method is enhanced");
return method.invoke(realObject, args);
}
}
}
控制台日志:
public void de.scrum_master.so.UserDaoImpl.save() -> class de.scrum_master.so.UserDaoImpl
impl method is enhanced
-----------
public abstract void de.scrum_master.so.UserDao.save() -> interface de.scrum_master.so.UserDao
real object method is enhanced
save
-----------
public abstract void de.scrum_master.so.UserDao.update() -> interface de.scrum_master.so.UserDao
update
请注意第real object method is enhanced
行。