在Spring AOP的规范中,提到:
Introduction: declaring additional methods or fields on behalf of a type. Spring AOP allows you to introduce new interfaces (and a corresponding implementation) to any advised object. For example, you could use an introduction to make a bean implement an IsModified interface, to simplify caching. (An introduction is known as an inter-type declaration in the AspectJ community.)
我不知道如何为建议类添加新字段,如果您有经验,可以举个例子吗?
最佳答案
演示 Spring AOP 介绍的代码导致了一个很长的答案。希望这有帮助
考虑以下界面
package rg.test.aop;
public interface UserService {
void sayHello();
}
以及两个实现
UserServiceOneImpl
package rg.test.aop.one;
import org.springframework.stereotype.Service;
import rg.test.aop.UserService;
@Service
public class UserServiceOneImpl implements UserService {
@Override
public void sayHello() {
System.out.println("One");
}
}
和 UserServiceTwoImpl
package rg.test.aop.two;
import org.springframework.stereotype.Service;
import rg.test.aop.UserService;
@Service
public class UserServiceTwoImpl implements UserService {
@Override
public void sayHello() {
System.out.println("Two");
}
}
以及通过AOP引入的接口(interface)及其实现
package rg.test.aop.intro;
public interface LoginTracker {
String FIELD = "Field";
Integer incrementLoginCount();
}
实现
package rg.test.aop.intro;
public class DefaultLoginTracker implements LoginTracker {
Integer count = 5;
@Override
public Integer incrementLoginCount() {
return ++count;
}
}
Spring AOP 建议向包下的所有类引入相同的内容 rg.test.aop.two
package rg.test.aop.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;
import rg.test.aop.intro.DefaultLoginTracker;
import rg.test.aop.intro.LoginTracker;
@Aspect
@Component
public class IntroTestAspect {
@DeclareParents(value="rg.test.aop.two.*+", defaultImpl=DefaultLoginTracker.class)
LoginTracker tracker;
}
要实现的接口(interface)由注释字段的类型决定。(这里是LoginTracker
)
任何匹配类型的 bean 都会实现 LoginTracker
接口(interface)。
现在,当您运行以下测试类时
//package and imports
public class IntroductionTest {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(IntroductionConfig.class);
LoginTracker tracker = ctx.getBean(LoginTracker.class);
System.out.println(tracker);
System.out.println("------------------------");
UserService userOne = (UserService) ctx.getBean("userServiceOneImpl");
UserService userTwo = (UserService) ctx.getBean("userServiceTwoImpl");
printDetails(userOne);
System.out.println("------------------------");
printDetails(userTwo);
ctx.registerShutdownHook();
}
private static void printDetails(Object obj) throws Exception {
System.out.println("Is LoginTracker type :"+LoginTracker.class.isAssignableFrom(obj.getClass()));
System.out.println("Is UserService type :"+UserService.class.isAssignableFrom(obj.getClass()));
System.out.println("Implemented Interfaces : ");
for (Class clazz : obj.getClass().getInterfaces()) {
System.out.println(clazz);
}
System.out.println("Methods : ");
for (Method method : obj.getClass().getMethods()) {
System.out.println(method);
}
System.out.println("Fields : ");
for (Field field : obj.getClass().getFields()) {
System.out.println(field);
}
// If Advised
if (Advised.class.isAssignableFrom(obj.getClass())) {
LoginTracker us = (LoginTracker) obj;
System.out.println(us.incrementLoginCount());
}
}
}
打印以下日志(注意:此处仅复制日志的相关部分以便于引用。)
rg.test.aop.two.UserServiceTwoImpl@c15d8b
------------------------
Is LoginTracker type :false
Is UserService type :true
Implemented Interfaces :
interface rg.test.aop.UserService
Methods :
public void rg.test.aop.one.UserServiceOneImpl.sayHello()
Fields :
------------------------
Is LoginTracker type :true
Is UserService type :true
Implemented Interfaces :
interface rg.test.aop.UserService
interface rg.test.aop.intro.LoginTracker
interface org.springframework.aop.SpringProxy
interface org.springframework.aop.framework.Advised
interface org.springframework.core.DecoratingProxy
Methods :
public final java.lang.Integer com.sun.proxy.$Proxy19.incrementLoginCount()
public final void com.sun.proxy.$Proxy19.sayHello()
Fields :
public static final java.lang.String rg.test.aop.intro.LoginTracker.FIELD
Count :6
日志显示为 UserServiceTwoImpl bean 引入的方法和字段。
关于java - Spring AOP : Declaring additional methods or fields on behalf of a type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61541503/