下面列出了com.google.inject.matcher.AbstractMatcher#org.aopalliance.intercept.MethodInterceptor 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
@Test
public void invokedAsynchronouslyOnProxyTarget() {
StaticApplicationContext context = new StaticApplicationContext();
context.registerBeanDefinition("postProcessor", new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class));
TestBean tb = new TestBean();
ProxyFactory pf = new ProxyFactory(ITestBean.class,
(MethodInterceptor) invocation -> invocation.getMethod().invoke(tb, invocation.getArguments()));
context.registerBean("target", ITestBean.class, () -> (ITestBean) pf.getProxy());
context.refresh();
ITestBean testBean = context.getBean("target", ITestBean.class);
testBean.test();
Thread mainThread = Thread.currentThread();
testBean.await(3000);
Thread asyncThread = testBean.getThread();
assertNotSame(mainThread, asyncThread);
context.close();
}
public DynamicAsyncInterfaceBean() {
ProxyFactory pf = new ProxyFactory(new HashMap<>());
DefaultIntroductionAdvisor advisor = new DefaultIntroductionAdvisor(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
assertTrue(!Thread.currentThread().getName().equals(originalThreadName));
if (Future.class.equals(invocation.getMethod().getReturnType())) {
return new AsyncResult<>(invocation.getArguments()[0].toString());
}
return null;
}
});
advisor.addInterface(AsyncInterface.class);
pf.addAdvisor(advisor);
this.proxy = (AsyncInterface) pf.getProxy();
}
public DynamicAsyncMethodsInterfaceBean() {
ProxyFactory pf = new ProxyFactory(new HashMap<>());
DefaultIntroductionAdvisor advisor = new DefaultIntroductionAdvisor(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
assertTrue(!Thread.currentThread().getName().equals(originalThreadName));
if (Future.class.equals(invocation.getMethod().getReturnType())) {
return new AsyncResult<>(invocation.getArguments()[0].toString());
}
return null;
}
});
advisor.addInterface(AsyncMethodsInterface.class);
pf.addAdvisor(advisor);
this.proxy = (AsyncMethodsInterface) pf.getProxy();
}
private Environment environmentForImage(int maxWidth, boolean invert) {
Map<String, Object> specification = new HashMap<>();
specification.put("banner.image.width", maxWidth);
specification.put("banner.image.invert", invert);
ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
proxyFactoryBean.setInterfaces(Environment.class);
proxyFactoryBean.addAdvice((MethodInterceptor) invocation -> {
String containsProperty = "containsProperty";
String getProperty = "getProperty";
List<String> toHandle = Arrays.asList(containsProperty, getProperty);
String methodName = invocation.getMethod().getName();
if (toHandle.contains(methodName)) {
String key = String.class.cast(invocation.getArguments()[0]);
if (methodName.equals(containsProperty)) {
return (specification.containsKey(key) || this.environment.containsProperty(key));
}
if (methodName.equals(getProperty)) {
return specification.getOrDefault(key, this.environment.getProperty(key));
}
}
return invocation.getMethod().invoke(this.environment, invocation.getArguments());
});
return Environment.class.cast(proxyFactoryBean.getObject());
}
/**
* creates a proxy that dispatches invocations to the currently bound {@link ProcessInstance}
*
* @return shareable {@link ProcessInstance}
*/
private Object createSharedProcessInstance() {
ProxyFactory proxyFactoryBean = new ProxyFactory(ProcessInstance.class, new MethodInterceptor() {
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
String methodName = methodInvocation.getMethod().getName() ;
logger.info("method invocation for " + methodName+ ".");
if(methodName.equals("toString"))
return "SharedProcessInstance";
ProcessInstance processInstance = Context.getExecutionContext().getProcessInstance();
Method method = methodInvocation.getMethod();
Object[] args = methodInvocation.getArguments();
Object result = method.invoke(processInstance, args);
return result;
}
});
return proxyFactoryBean.getProxy(this.classLoader);
}
@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
/**
* InvocationHandler 接口中的 invoke 方法具体实现,封装了具体的代理逻辑
*
* @param proxy
* @param method
* @param args
* @return 代理方法或原方法的返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodMatcher methodMatcher = advised.getMethodMatcher();
// 使用方法匹配器 methodMatcher 测试 bean 中原始方法 method 是否符合匹配规则
if (methodMatcher != null && methodMatcher.matchers(method, advised.getTargetSource().getTargetClass())) {
// 获取 Advice。MethodInterceptor 的父接口继承了 Advice
MethodInterceptor methodInterceptor = advised.getMethodInterceptor();
// 将 bean 的原始 method 封装成 MethodInvocation 实现类对象,
// 将生成的对象传给 Adivce 实现类对象,执行通知逻辑
return methodInterceptor.invoke(
new ReflectiveMethodInvocation(advised.getTargetSource().getTarget(), method, args));
} else {
// 当前 method 不符合匹配规则,直接调用 bean 中的原始 method
return method.invoke(advised.getTargetSource().getTarget(), args);
}
}
@Test
public void testNullPrimitiveWithJdkProxy() {
class SimpleFoo implements Foo {
@Override
public int getValue() {
return 100;
}
}
SimpleFoo target = new SimpleFoo();
ProxyFactory factory = new ProxyFactory(target);
factory.addAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
return null;
}
});
Foo foo = (Foo) factory.getProxy();
thrown.expect(AopInvocationException.class);
thrown.expectMessage("Foo.getValue()");
assertEquals(0, foo.getValue());
}
@Test
public void invokedAsynchronouslyOnProxyTarget() {
StaticApplicationContext context = new StaticApplicationContext();
context.registerBeanDefinition("postProcessor", new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class));
TestBean tb = new TestBean();
ProxyFactory pf = new ProxyFactory(ITestBean.class,
(MethodInterceptor) invocation -> invocation.getMethod().invoke(tb, invocation.getArguments()));
context.registerBean("target", ITestBean.class, () -> (ITestBean) pf.getProxy());
context.refresh();
ITestBean testBean = context.getBean("target", ITestBean.class);
testBean.test();
Thread mainThread = Thread.currentThread();
testBean.await(3000);
Thread asyncThread = testBean.getThread();
assertNotSame(mainThread, asyncThread);
context.close();
}
/**
* Instantiates a new managed subsystem proxy factory.
*/
public SubsystemProxyFactory()
{
addAdvisor(new DefaultPointcutAdvisor(new MethodInterceptor()
{
public Object invoke(MethodInvocation mi) throws Throwable
{
Method method = mi.getMethod();
try
{
return method.invoke(locateBean(mi), mi.getArguments());
}
catch (InvocationTargetException e)
{
// Unwrap invocation target exceptions
throw e.getTargetException();
}
}
}));
}
/**
* Binds an exception trap on all interface methods of all classes bound against an interface.
* Individual methods may opt out of trapping by annotating with {@link AllowUnchecked}.
* Only void methods are allowed, any non-void interface methods must explicitly opt out.
*
* @param binder The binder to register an interceptor with.
* @param wrapInterface Interface whose methods should be wrapped.
* @throws IllegalArgumentException If any of the non-whitelisted interface methods are non-void.
*/
public static void bindExceptionTrap(Binder binder, Class<?> wrapInterface)
throws IllegalArgumentException {
Set<Method> disallowed = ImmutableSet.copyOf(Iterables.filter(
ImmutableList.copyOf(wrapInterface.getMethods()),
Predicates.and(Predicates.not(IS_WHITELISTED), Predicates.not(VOID_METHOD))));
Preconditions.checkArgument(disallowed.isEmpty(),
"Non-void methods must be explicitly whitelisted with @AllowUnchecked: %s", disallowed);
Matcher<Method> matcher =
Matchers.not(WHITELIST_MATCHER).and(interfaceMatcher(wrapInterface, false));
binder.bindInterceptor(Matchers.subclassesOf(wrapInterface), matcher,
new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
try {
return invocation.proceed();
} catch (RuntimeException e) {
LOG.warn("Trapped uncaught exception: " + e, e);
return null;
}
}
});
}
public AopAccessLoggerSupport() {
setAdvice((MethodInterceptor) methodInvocation -> {
MethodInterceptorHolder methodInterceptorHolder = MethodInterceptorHolder.create(methodInvocation);
AccessLoggerInfo info = createLogger(methodInterceptorHolder);
Object response;
try {
eventPublisher.publishEvent(new AccessLoggerBeforeEvent(info));
listeners.forEach(listener -> listener.onLogBefore(info));
response = methodInvocation.proceed();
info.setResponse(response);
} catch (Throwable e) {
info.setException(e);
throw e;
} finally {
info.setResponseTime(System.currentTimeMillis());
//触发监听
eventPublisher.publishEvent(new AccessLoggerAfterEvent(info));
listeners.forEach(listener -> listener.onLogger(info));
}
return response;
});
}
/**
* AOP切点
* @author Frodez
* @date 2019-05-10
*/
@Override
public Advice getAdvice() {
/**
* 请求限流
* @param JoinPoint AOP切点
* @author Frodez
* @date 2018-12-21
*/
return (MethodInterceptor) invocation -> {
Pair<RateLimiter, Long> pair = limitCache.get(ReflectUtil.fullName(invocation.getMethod()));
if (!pair.getKey().tryAcquire(pair.getValue(), DefTime.UNIT)) {
return Result.busy().async();
}
return invocation.proceed();
};
}
@Test
public void testNullPrimitiveWithJdkProxy() {
class SimpleFoo implements Foo {
@Override
public int getValue() {
return 100;
}
}
SimpleFoo target = new SimpleFoo();
ProxyFactory factory = new ProxyFactory(target);
factory.addAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
return null;
}
});
Foo foo = (Foo) factory.getProxy();
thrown.expect(AopInvocationException.class);
thrown.expectMessage("Foo.getValue()");
assertEquals(0, foo.getValue());
}
/**
* AOP切点
* @author Frodez
* @date 2019-05-10
*/
@Override
public Advice getAdvice() {
/**
* 在一定时间段内拦截重复请求
* @param JoinPoint AOP切点
* @author Frodez
* @date 2018-12-21
*/
return (MethodInterceptor) invocation -> {
HttpServletRequest request = MVCUtil.request();
String name = ReflectUtil.fullName(invocation.getMethod());
String key = KeyGenerator.servletKey(name, request);
if (checker.check(key)) {
log.info("重复请求:IP地址{}", ServletUtil.getAddr(request));
return Result.repeatRequest().async();
}
checker.lock(key, timeoutCache.get(name));
return invocation.proceed();
};
}
/**
* AOP切点
* @author Frodez
* @date 2019-05-10
*/
@Override
public Advice getAdvice() {
return (MethodInterceptor) invocation -> {
Method method = invocation.getMethod();
String name = ReflectUtil.fullName(method);
if (method.getParameterCount() != 0) {
Parameter[] parameters = method.getParameters();
Object[] args = invocation.getArguments();
Map<String, Object> paramMap = new HashMap<>(parameters.length);
for (int i = 0; i < parameters.length; ++i) {
paramMap.put(parameters[i].getName(), args[i]);
}
log.info("{} 请求参数:{}", name, JSONUtil.string(paramMap));
} else {
log.info("{} 本方法无入参", name);
}
Object result = invocation.proceed();
if (method.getReturnType() != Void.class) {
log.info("{} 返回值:{}", name, JSONUtil.string(result));
} else {
log.info("{} 本方法返回值类型为void", name);
}
return result;
};
}
public static void bindThriftDecorator(
Binder binder,
Matcher<? super Class<?>> classMatcher,
MethodInterceptor interceptor) {
binder.bindInterceptor(
classMatcher,
Matchers.returns(Matchers.subclassesOf(Response.class)),
interceptor);
binder.requestInjection(interceptor);
}
@Override
public <I> void hear(TypeLiteral<I> literal, TypeEncounter<I> encounter) {
Class<? super I> type = literal.getRawType();
for (Method method : type.getMethods()) {
ParameterizedTimed annotation = method.getAnnotation(ParameterizedTimed.class);
if (annotation == null) {
continue;
}
String metricType = annotation.type();
if(metricType == null || metricType.isEmpty()) {
metricType = type.getSimpleName().replaceAll("\\$$", "");
}
String metricName = annotation.name();
if(metricName == null || metricName.isEmpty()) {
metricName = method.getName();
}
String metric = MetricRegistry.name(_group, metricType, metricName);
final Timer timer = _metricRegistry.timer(metric);
encounter.bindInterceptor(Matchers.only(method), new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Timer.Context time = timer.time();
try {
return invocation.proceed();
} finally {
time.stop();
}
}
});
}
}
@Test
public void testDeclaredException() throws Throwable {
final Exception expectedException = new Exception();
// Test return value
MethodInterceptor mi = new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
throw expectedException;
}
};
AdvisedSupport pc = new AdvisedSupport(new Class<?>[] {ITestBean.class});
pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
pc.addAdvice(mi);
// We don't care about the object
mockTargetSource.setTarget(new Object());
pc.setTargetSource(mockTargetSource);
AopProxy aop = createAopProxy(pc);
try {
ITestBean tb = (ITestBean) aop.getProxy();
// Note: exception param below isn't used
tb.exceptional(expectedException);
fail("Should have thrown exception raised by interceptor");
}
catch (Exception thrown) {
assertEquals("exception matches", expectedException, thrown);
}
}
@SuppressWarnings("unchecked")
private void addPoolAdvice(ProxyFactory proxyFactory, ThriftClient annotataion) {
proxyFactory.addAdvice((MethodInterceptor) methodInvocation -> getObject(
methodInvocation,
getThriftClientKey(
(Class<? extends TServiceClient>) methodInvocation.getMethod().getDeclaringClass(),
annotataion
)
));
}
@SuppressWarnings("unchecked")
private void addPoolAdvice(ProxyFactory proxyFactory) {
proxyFactory.addAdvice((MethodInterceptor) methodInvocation -> getObject(
methodInvocation,
getThriftClientKey(
(Class<? extends TServiceClient>) methodInvocation.getMethod().getDeclaringClass()
)
));
}
@Test
public void testInterceptorWithoutJoinpoint() {
final TestBean target = new TestBean("tb");
ITestBean proxy = ProxyFactory.getProxy(ITestBean.class, (MethodInterceptor) invocation -> {
assertNull(invocation.getThis());
return invocation.getMethod().invoke(target, invocation.getArguments());
});
assertEquals("tb", proxy.getName());
}
/**
* @param context if true, want context
*/
private void testContext(final boolean context) throws Throwable {
final String s = "foo";
// Test return value
MethodInterceptor mi = new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if (!context) {
assertNoInvocationContext();
}
else {
assertNotNull("have context", ExposeInvocationInterceptor.currentInvocation());
}
return s;
}
};
AdvisedSupport pc = new AdvisedSupport(ITestBean.class);
if (context) {
pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
}
pc.addAdvice(mi);
// Keep CGLIB happy
if (requiresTarget()) {
pc.setTarget(new TestBean());
}
AopProxy aop = createAopProxy(pc);
assertNoInvocationContext();
ITestBean tb = (ITestBean) aop.getProxy();
assertNoInvocationContext();
assertSame("correct return value", s, tb.getName());
}
@Test
public void testDeclaredException() throws Throwable {
final Exception expectedException = new Exception();
// Test return value
MethodInterceptor mi = new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
throw expectedException;
}
};
AdvisedSupport pc = new AdvisedSupport(ITestBean.class);
pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
pc.addAdvice(mi);
// We don't care about the object
mockTargetSource.setTarget(new TestBean());
pc.setTargetSource(mockTargetSource);
AopProxy aop = createAopProxy(pc);
try {
ITestBean tb = (ITestBean) aop.getProxy();
// Note: exception param below isn't used
tb.exceptional(expectedException);
fail("Should have thrown exception raised by interceptor");
}
catch (Exception thrown) {
assertEquals("exception matches", expectedException, thrown);
}
}
@Test
public void testUndeclaredUncheckedException() throws Throwable {
final RuntimeException unexpectedException = new RuntimeException();
// Test return value
MethodInterceptor mi = new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
throw unexpectedException;
}
};
AdvisedSupport pc = new AdvisedSupport(ITestBean.class);
pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
pc.addAdvice(mi);
// We don't care about the object
pc.setTarget(new TestBean());
AopProxy aop = createAopProxy(pc);
ITestBean tb = (ITestBean) aop.getProxy();
try {
// Note: exception param below isn't used
tb.getAge();
fail("Should have wrapped exception raised by interceptor");
}
catch (RuntimeException thrown) {
assertEquals("exception matches", unexpectedException, thrown);
}
}
/**
* There are times when we want to call proceed() twice.
* We can do this if we clone the invocation.
*/
@Test
public void testCloneInvocationToProceedThreeTimes() throws Throwable {
TestBean tb = new TestBean();
ProxyFactory pc = new ProxyFactory(tb);
pc.addInterface(ITestBean.class);
MethodInterceptor twoBirthdayInterceptor = new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// Clone the invocation to proceed three times
// "The Moor's Last Sigh": this technology can cause premature aging
MethodInvocation clone1 = ((ReflectiveMethodInvocation) mi).invocableClone();
MethodInvocation clone2 = ((ReflectiveMethodInvocation) mi).invocableClone();
clone1.proceed();
clone2.proceed();
return mi.proceed();
}
};
@SuppressWarnings("serial")
StaticMethodMatcherPointcutAdvisor advisor = new StaticMethodMatcherPointcutAdvisor(twoBirthdayInterceptor) {
@Override
public boolean matches(Method m, @Nullable Class<?> targetClass) {
return "haveBirthday".equals(m.getName());
}
};
pc.addAdvisor(advisor);
ITestBean it = (ITestBean) createProxy(pc);
final int age = 20;
it.setAge(age);
assertEquals(age, it.getAge());
// Should return the age before the third, AOP-induced birthday
assertEquals(age + 2, it.haveBirthday());
// Return the final age produced by 3 birthdays
assertEquals(age + 3, it.getAge());
}
/**
* Wrap each concrete endpoint instance with an AOP proxy,
* exposing the message listener's interfaces as well as the
* endpoint SPI through an AOP introduction.
*/
@Override
public MessageEndpoint createEndpoint(XAResource xaResource) throws UnavailableException {
GenericMessageEndpoint endpoint = (GenericMessageEndpoint) super.createEndpoint(xaResource);
ProxyFactory proxyFactory = new ProxyFactory(this.messageListener);
DelegatingIntroductionInterceptor introduction = new DelegatingIntroductionInterceptor(endpoint);
introduction.suppressInterface(MethodInterceptor.class);
proxyFactory.addAdvice(introduction);
return (MessageEndpoint) proxyFactory.getProxy();
}
@Override
protected void configure() {
final MethodInterceptor interceptor = new ValidationInterceptor();
bindInterceptor(Matchers.any(), Matchers.annotatedWith(Validate.class), interceptor);
requestInjection(interceptor);
bind(ConstraintValidatorFactory.class).to(GuiceConstraintValidatorFactory.class);
}