【发布时间】:2020-05-01 11:21:50
【问题描述】:
在 Spring AOP 的规范中提到:
简介:代表一个类型声明额外的方法或字段。 Spring AOP 允许您向任何建议的对象引入新接口(和相应的实现)。例如,您可以使用介绍使 bean 实现 IsModified 接口,以简化缓存。 (介绍在 AspectJ 社区中称为类型间声明。)
我不知道如何为建议课程添加新字段,如果您有经验,能否举个例子?
【问题讨论】:
标签: java spring spring-aop
在 Spring AOP 的规范中提到:
简介:代表一个类型声明额外的方法或字段。 Spring AOP 允许您向任何建议的对象引入新接口(和相应的实现)。例如,您可以使用介绍使 bean 实现 IsModified 接口,以简化缓存。 (介绍在 AspectJ 社区中称为类型间声明。)
我不知道如何为建议课程添加新字段,如果您有经验,能否举个例子?
【问题讨论】:
标签: java spring spring-aop
演示 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 引入
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;
}
要实现的接口由注解字段的类型决定。(这里LoginTracker)
任何匹配类型的 bean 都实现 LoginTracker 接口。
现在当你运行下面的测试类时
//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 引入的方法和字段。
【讨论】: