Add DAO Capabilities to a Class Without Changing Business Code Using Spring IntroductionAdvisor
This guide demonstrates how to give a Spring bean class DAO functionality without altering its source code by using IntroductionAdvisor, showing the required interfaces, interceptor, advisor definition, and a complete runnable example with output.
Environment
Spring 5.2.14
Problem Statement
How can a class acquire a new capability, such as implementing a XXXDAO interface, without modifying its business code?
55.1 IntroductionAdvisor Overview
Differences between IntroductionAdvisor and PointcutAdvisor :
IntroductionAdvisor applies only at the class level.
It can only apply to Introduction type advice, while PointcutAdvisor works with any advice type.
The advice of an IntroductionAdvisor must implement the target interface; PointcutAdvisor has no such requirement.
55.2 Using IntroductionAdvisor
Assume we want the business class CustomDAO to gain the capabilities of the DesignDAO interface.
55.2.1 Target Interface
public interface DesignDAO {
public void design();
}55.2.2 Introduction Interceptor
public class CustomIntroductionInterceptor implements IntroductionInterceptor, DesignDAO {
// Determine whether the current interceptor implements the target interface
@Override
public boolean implementsInterface(Class<?> intf) {
return intf.isAssignableFrom(this.getClass());
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("我是通知类:IntroductionInterceptor");
// If the method's declaring class implements the target interface, invoke it on this interceptor
if (implementsInterface(invocation.getMethod().getDeclaringClass())) {
return invocation.getMethod().invoke(this, invocation.getArguments());
}
return invocation.proceed();
}
@Override
public void design() {
System.out.println("接口实现了");
}
}55.2.3 Defining the IntroductionAdvisor
@Component
public class CustomIntroductionAdvisor implements IntroductionAdvisor {
// Provide the advice
@Override
public Advice getAdvice() {
return new CustomIntroductionInterceptor();
}
// Not used; return true directly
@Override
public boolean isPerInstance() {
return true;
}
// Declare the interfaces that should be introduced
@Override
public Class<?>[] getInterfaces() {
return new Class<?>[] { DesignDAO.class };
}
// Filter classes; only those assignable from CustomDAO are matched
@Override
public ClassFilter getClassFilter() {
return new ClassFilter() {
@Override
public boolean matches(Class<?> clazz) {
return CustomDAO.class.isAssignableFrom(clazz);
}
};
}
// Optional validation of the advice against the declared interfaces
@Override
public void validateInterfaces() throws IllegalArgumentException {
// Refer to DefaultIntroductionAdvisor for implementation details
}
}55.2.4 Validation Bean
@Component
public class CustomerDAOImpl implements CustomDAO {
public void update() {
System.out.println("更新数据..." + this.getClass());
}
public void save() {
System.out.println("保存方法..." + this.getClass());
}
}Running the Example
The business class does not implement DesignDAO. The following main class shows how the IntroductionAdvisor makes the bean acquire that capability.
public class LauncherMain {
public static void main(String[] args) {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("com.pack");
CustomDAO dao = ctx.getBean(CustomDAO.class);
System.out.println(dao.getClass());
System.out.println(Arrays.toString(dao.getClass().getInterfaces()));
dao.save();
dao.update();
if (DesignDAO.class.isAssignableFrom(dao.getClass())) {
DesignDAO ddao = (DesignDAO) dao;
System.out.println("IntroductionAdvisor start...");
ddao.design();
System.out.println("IntroductionAdvisor end...");
}
ctx.close();
}
}Execution Result
class com.sun.proxy.$Proxy14
[interface com.pack.dao.CustomDAO, interface com.pack.interfaces.DesignDAO, interface org.springframework.aop.SpringProxy, interface org.springframework.aop.framework.Advised, interface org.springframework.core.DecoratingProxy]
我是通知类:IntroductionInterceptor, interface com.pack.dao.CustomDAO
intf: interface com.pack.dao.CustomDAO
我被调用了...
保存方法...class com.pack.dao.CustomerDAOImpl
我是通知类:IntroductionInterceptor, interface com.pack.dao.CustomDAO
intf: interface com.pack.dao.CustomDAO
更新数据...class com.pack.dao.CustomerDAOImpl
IntroductionAdvisor start...
我是通知类:IntroductionInterceptor, interface com.pack.interfaces.DesignDAO
intf: interface com.pack.interfaces.DesignDAO
接口实现了
IntroductionAdvisor end...This output confirms that the proxy created by Spring implements both CustomDAO and DesignDAO, allowing the original bean to invoke design() without any source code changes.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
