我试图弄清楚如何捕获在PHP中调用对象的任何方法.我知道魔术函数__call
,但它仅针对被调用对象上不存在的方法触发.
例如,我有这样的事情:
class Foo
{
public function bar()
{
echo 'foobar';
}
public function override($method_name,$method_args)
{
echo 'Calling method ',$method_name,'<br />';
$this->$method_name($method_args); //dirty, but working
}
}
Run Code Online (Sandbox Code Playgroud)
当我这样做时:
$foo = new Foo();
$foo->bar();
Run Code Online (Sandbox Code Playgroud)
我想要这个输出:
Calling method bar
foobar
Run Code Online (Sandbox Code Playgroud)
而不是这一个:
foobar
Run Code Online (Sandbox Code Playgroud)
有什么方法可以做到这一点吗?请帮忙 :)
我最近注意到,Spring成功拦截了@Configuration类中的内部类函数调用,但没有拦截常规的bean。
这样的电话
@Repository
public class CustomerDAO {
@Transactional(value=TxType.REQUIRED)
public void saveCustomer() {
// some DB stuff here...
saveCustomer2();
}
@Transactional(value=TxType.REQUIRES_NEW)
public void saveCustomer2() {
// more DB stuff here
}
}
Run Code Online (Sandbox Code Playgroud)
未能启动新事务,因为尽管在CustomerDAO代理中执行了saveCustomer()的代码,但在已解包的CustomerDAO类中执行了saveCustomer2()的代码,正如我在调试器中查看“ this”所看到的,等等Spring没有机会拦截对saveCustomer2的调用。
但是,在以下示例中,当transactionManager()调用createDataSource()时,它将被正确拦截并调用代理的createDataSource(),而不是未包装类的调用,而在调试器中查看“ this”可以证明这一点。
@Configuration
public class PersistenceJPAConfig {
@Bean
public DriverManagerDataSource createDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
//dataSource.set ... DB stuff here
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager( ){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(createDataSource());
return transactionManager;
}
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,为什么在第二个示例中Spring可以正确地拦截内部类函数调用,而在第一个示例中则不能。是否使用不同类型的动态代理?
编辑: 从这里的答案和其他来源,我现在了解以下内容:@Transactional是使用Spring AOP实现的,其中代理模式通过包装/组合用户类来执行。AOP代理足够通用,因此许多方面都可以链接在一起,并且可以是CGLib代理或Java动态代理。
在@Configuration类中,Spring还使用CGLib创建一个从用户@Configuration类继承的增强类,并在调用用户的/ super函数之前用做一些额外工作的函数覆盖用户的@Bean函数,例如检查是否是否是该函数的首次调用。该课程是代理吗?这取决于定义。您可能会说这是一个使用真实对象继承的代理,而不是使用组合包装。
总而言之,从这里给出的答案中,我了解到这是两种完全不同的机制。为什么做出这些设计选择是另一个悬而未决的问题。
我写了一个这样的例子
简单计算器类:
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
}
Run Code Online (Sandbox Code Playgroud)
实现了DynamicProxy提供的"IInterceptor"
[Serializable]
public abstract class Interceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
ExecuteBefore(invocation);
invocation.Proceed();
ExecuteAfter(invocation);
}
protected abstract void ExecuteAfter(IInvocation invocation);
protected abstract void ExecuteBefore(IInvocation invocation);
}
Run Code Online (Sandbox Code Playgroud)
创建了一个Interceptor类,并继承自"Interceptor"类
public class CalculatorInterceptor : Interceptor
{
protected override void ExecuteBefore(Castle.DynamicProxy.IInvocation invocation)
{
Console.WriteLine("Start");
}
protected override void ExecuteAfter(Castle.DynamicProxy.IInvocation invocation)
{
Console.WriteLine("End");
}
}
Run Code Online (Sandbox Code Playgroud)
但是当我用它不工作!
static void Main(string[] args)
{
ProxyGenerator generator …
Run Code Online (Sandbox Code Playgroud) c# castle-dynamicproxy dynamic-proxy interceptor interception
我决定发布这个问题并回答这个问题的评论:
如何处理子视图中的点击,并触摸父ViewGroups?
我将粘贴评论:
假设我想仅仅为了处理一些孩子而覆盖触摸事件,我可以在这个函数中做些什么让它工作?我的意思是,对于一些孩子来说,它会像往常一样工作,对于一些人来说,父母视图将决定他们是否会接触到触摸事件.
所以问题是这样的:我如何阻止父母onTouchEvent()
重写某些子元素onTouchEvent()
,同时让它覆盖其他子元素?
我需要拦截网页内单元格内容的任何变化.
以下代码向我显示addEventListener不起作用.
function modifyText() {
alert("!");
}
var el=document.getElementById("mycell");
el.innerHTML="a"
el.addEventListener("change", modifyText, false);
// After next instruction I expect an alert message but it does not appear...
el.innerHTML="Z";
Run Code Online (Sandbox Code Playgroud)
代码只是一个玩具示例.在我的实际情况中,页面中的更改(因此也在单元格中)是由我无法控制的webapp进行的.
我做了一个小的共享库,试图拦截open,open64,stat和stat64 sys调用.当我导出LD_PRELOAD并运行oracle的sqlplus时,我可以看到open和open64调用的痕迹,但没有stat和stat64调用的痕迹.共享库是一个单独的c文件,其中包含sys调用的所有定义.为什么有些系统调用被截获而其他系统没有被截获?谢谢你的帮助.
我们的应用程序有很多对Task.Factory.StartNew(Action动作)的调用.不幸的是,在执行此操作时,未设置文化,此外,没有错误处理.我从一个可以同时执行这两个操作的入门类开始:
public static class TaskBuilder
{
private static Action<System.Exception> _exceptionCallback;
public static Task StartNew(Action action, CultureInfo cultureInfo, Action<System.Exception> exceptionCallback)
{
_exceptionCallback = exceptionCallback;
return Task.Factory.StartNew(() =>
{
Thread.CurrentThread.CurrentUICulture = cultureInfo;
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureInfo.Name);
action.Invoke();
}).ContinueWith(t => ManageException(t.Exception), TaskContinuationOptions.OnlyOnFaulted);
}
private static void ManageException(System.Exception e)
{
if (_exceptionCallback != null)
{
_exceptionCallback(e);
}
}
}
Run Code Online (Sandbox Code Playgroud)
但后来我意识到更好的方法是拦截器.我想拦截对StartNew的调用,以便新线程包含文化和错误处理代码.我的尝试产生了以下代码:
public class TaskInterceptionHandler : ICallHandler
{
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
Thread.CurrentThread.CurrentUICulture = // How do I get parent cultureInfo?;
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureInfo.Name); …
Run Code Online (Sandbox Code Playgroud) 我一直很难找到一个易于学习的教程或使用Ninject使用拦截扩展的例子,或者理想情况下是一个工作示例.
我已经尝试了下面的教程,但是立即遇到了让命名空间用于the Intercept()
调用的问题:
http://innovatian.com/2010/03/using-ninject-extensions-interception-part-1-the-basics/
有没有办法在C#unity中如何使用属性拦截并将对象注册代码保存在XML文件中(如app.config)?如果是的话,你能为我提供代码,这样的注册应该怎么样?我做了很多解决方法,但没有找到解决此问题的方法.
找不到任何关于如何使用剧作家模拟/存根服务器端请求的好文档。
一个例子是拦截 nextjs 中的 getServerSideProps:点击路由使服务器发出请求(db API 等)。然后它可以执行一些业务逻辑(也应该通过测试涵盖),然后将其作为 props 传递给组件,然后发送到客户端(在服务器端渲染)。
我希望找到答案,即在不将一些测试逻辑混合到业务逻辑中的情况下模拟数据库 API 请求。
interception ×10
c# ×3
android ×1
android-view ×1
aop ×1
c ×1
interceptor ×1
java ×1
javascript ×1
mocking ×1
ninject ×1
object ×1
parent-child ×1
php ×1
playwright ×1
preload ×1
proxy ×1
spring ×1
stat ×1
stubbing ×1
system-calls ×1
testing ×1
touch-event ×1