首先定义一个简单的Service:
public interface IDemoService { void add(int a, int b);}@Servicepublic 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)@Documentedpublic @interface Log {}复制代码
使用BeanPostProcesser来生成自定义的代理对象:
@Servicepublic 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 结束执行
源代码地址:解决了如果有一个方法加了@Log注解,那么这个类所有的方法都会执行Log的情况。至于原理嘛。。下篇讲述。。《Java并发编程系统》是一本系统介绍Java并发编程方面的书籍。囊括了从最基本的并发原理到顶层API的使用,以及到最后的深入实践。适合零基础想深入学习Java并发编程的人员,本书包含了Java并发的基本原理,并发包的使用等。 阅读地址: