首先定義一個簡單的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併發的基本原理,併發包的使用等。