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.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Add DAO Capabilities to a Class Without Changing Business Code Using Spring IntroductionAdvisor

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

daointroductionadvisor
Spring Full-Stack Practical Cases
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.