Spring 自定義註解(上)

徐家三少發表於2017-08-10

首先定義一個簡單的Service:

public interface IDemoService {

    void add(int a, int b);

}
@Service
public class DemoServiceImpl implements  IDemoService {

    @Log
    public void add(int a, int b) {
        System.out.println(Thread.currentThread().getName());
        System.out.println(a + b);

    }

}複製程式碼

假設@Log註解可以用來記錄每個函式的執行情況:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {

}複製程式碼

使用BeanPostProcesser來生成自定義的代理物件:

@Service
public class LogAnnotationBeanPostProcesser extends AbstractBeanFactoryAwareAdvisingPostProcessor {

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        super.setBeanFactory(beanFactory);
        LogAnnotationAdvisor advisor = new LogAnnotationAdvisor();
        advisor.setBeanFactory(beanFactory);
        this.advisor = advisor;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        Method[] methods = ReflectionUtils.getAllDeclaredMethods(bean.getClass());
        for (Method method : methods) {
            if (method.isAnnotationPresent(Log.class)) {
                ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
                if (!proxyFactory.isProxyTargetClass()) {
                    evaluateProxyInterfaces(bean.getClass(), proxyFactory);
                }
                proxyFactory.addAdvisor(this.advisor);
                customizeProxyFactory(proxyFactory);
                return proxyFactory.getProxy(getProxyClassLoader());
            }
        }
        return bean;

    }

}複製程式碼

LogAnnotationAdvisor用來處理切面:

public class LogAnnotationAdvisor  implements BeanFactoryAware,Advisor{

    private Advice advice;

    public  LogAnnotationAdvisor(){

        this.advice=new LogAnnotationInterceptor();
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {


    }

    @Override
    public Advice getAdvice() {


        return this.advice;
    }

    @Override
    public boolean isPerInstance() {
        // TODO Auto-generated method stub
        return false;
    }

}複製程式碼

當然例項處理交給了:

public class LogAnnotationInterceptor    implements MethodInterceptor, Ordered{

    @Override
    public int getOrder() {



        return Ordered.HIGHEST_PRECEDENCE;
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("開始執行");
        invocation.proceed();

        System.out.println("結束執行");
        return null;
    }

}複製程式碼

使用:

public class Main {
    public static void main(String[] args) {
        @SuppressWarnings("resource")
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");    
         IDemoService demoService = context.getBean(IDemoService.class);    
//         AsyncAnnotationBeanPostProcessor     
        demoService.add(1, 2);

    }
}複製程式碼

輸出:
開始執行 main 3 結束執行
原始碼地址:github.com/slowlizard/…
解決了如果有一個方法加了@Log註解,那麼這個類所有的方法都會執行Log的情況。
至於原理嘛。。下篇講述。。
《Java併發程式設計系統》是一本系統介紹Java併發程式設計方面的書籍。囊括了從最基本的併發原理到頂層API的使用,以及到最後的深入實踐。適合零基礎想深入學習Java併發程式設計的人員,本書包含了Java併發的基本原理,併發包的使用等。

閱讀地址:
yuedu.baidu.com/ebook/d09e3…

相關文章