我在这个问题上找到了几个讨论主题 - 但没有任何内容在一个主题下对所有三种机制进行了比较.
所以这是我的问题......
我需要审核数据库更改 - 插入\ updates \删除到业务对象.
我可以想到三种方法来做到这一点
1)DB触发器
2)Hibernate拦截器
3)Spring AOP
(这个问题特定于Spring\Hibernate\RDBMS-我猜这对java\c#或hibernate \nhibernate-是中立的 - 但如果你的答案依赖于C++或Java或者hibernate的具体实现 - 请注明)
选择其中一种策略有哪些优缺点?
我不是要求实现细节.-这是一个设计讨论.
我希望我们可以将其作为社区维基的一部分
我想用Spring/AOP和注释实现声明性安全性.正如您在下一个代码示例中所看到的,我使用了限制注释和参数"allowedRoles"来定义允许执行建议方法的人员.
@Restricted(allowedRoles="jira-administrators")
public void setPassword(...) throws UserMgmtException {
// set password code
...
}
Run Code Online (Sandbox Code Playgroud)
现在,问题是在我的建议中我无法访问已定义的注释:
public Object checkPermission(ProceedingJoinPoint pjp) throws Throwable {
Signature signature = pjp.getSignature();
System.out.println("Allowed:" + rolesAllowedForJoinPoint(pjp));
...
}
private Restricted rolesAllowedForJoinPoint(ProceedingJoinPoint thisJoinPoint)
{
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
Method targetMethod = methodSignature.getMethod();
return targetMethod.getAnnotation(Restricted.class);
}
Run Code Online (Sandbox Code Playgroud)
上面的方法总是返回null(根本没有找到注释).有一个简单的解决方案吗?
我读了一些关于使用AspectJ代理的内容,但我不想使用这个代理.
我在"aspectj"模式下使用Spring的声明式事务(@Transactional注释).它在大多数情况下都可以完全像它应该的那样工作,但对于其中一个它没有.我们可以称之为Lang(因为这就是它实际上所称的).
我已经能够确定加载时间织布机的问题.通过打开aop.xml中的debug和verbose日志记录,它列出了所有正在编织的类.Lang根本没有在日志中提到有问题的类.
然后我在顶部放置了一个断点Lang,导致Eclipse在Lang加载类时挂起线程.当LTW编织其他类时,这个断点被击中!所以我猜测它要么编织也要Lang失败并且不输出,或者其他一些类有一个引用强制它Lang在实际有机会编织它之前加载.
我不确定如何继续调试这个,因为我无法以较小的规模重现它.有关如何继续的任何建议?
更新:其他线索也欢迎.例如,LTW实际上如何运作?似乎有很多魔法发生.是否有任何选项可以从LTW获得更多的调试输出?我目前有:
<weaver options="-XnoInline -Xreweavable -verbose -debug -showWeaveInfo">
Run Code Online (Sandbox Code Playgroud)
我忘了汤姆之前提到它:弹簧剂被用来允许LTW,即InstrumentationLoadTimeWeaver.
根据Andy Clement的建议,我决定检查AspectJ变压器是否甚至通过了这门课程.我放了一个断点ClassPreProcessorAgent.transform(..),看起来这个Lang类甚至都没有到达那个方法,尽管它被与其他类(Jetty的WebAppClassLoader的一个实例)相同的类加载器加载.
然后我接着断了一个断点InstrumentationLoadTimeWeaver$FilteringClassFileTransformer.transform(..).甚至没有一个被击中Lang.我相信应该为所有加载的类调用该方法,无论他们使用什么类加载器.这开始看起来像:
Lang在Eclipse报告时没有加载接下来的线索:我打开了-verbose:class,看起来好像Lang 是过早加载 - 可能是在变压器添加到Instrumentation之前.奇怪的是,我的Eclipse断点没有捕获到这个加载.
这意味着Spring是新的嫌疑人.在ConfigurationClassPostProcessor负载类中似乎有一些处理来检查它们.这可能与我的问题有关.
这些行ConfigurationClassBeanDefinitionReader导致Lang类被读取:
else if (metadata.isAnnotated(Component.class.getName()) ||
metadata.hasAnnotatedMethods(Bean.class.getName())) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
return true;
}
Run Code Online (Sandbox Code Playgroud)
特别是对类的metadata.hasAnnotatedMethods()调用getDeclaredMethods(),它加载该类中所有方法的所有参数类.我猜这可能不是问题的结束,因为我认为这些类应该被卸载.JVM是否可以出于不可知的原因缓存类实例?
在编写方面时,如何测试它们是否匹配,以及在我需要时调用它们?
我正在使用@AspectSpring 2.5.6的声明.
我不关心功能,否则提取和测试.
我在基于spring mvc的应用程序中使用Aspect进行日志记录活动.我正在使用@controller注释来定义我的应用程序中的任何控制器.我在两个不同的包中有两个不同的控制器说
我可以通过使用将方面应用于一个特定的控制器包
<aop:config>
<aop:pointcut id="pointcut1"
expression="execution(* package1.*.*(..))"
id="policy1" />
<aop:aspect ref="aspect1" order="1">
<aop:before pointcut-ref="pointcut1" method="before" arg-names="joinPoint" />
<aop:after-returning returning="returnValue" arg-names="joinPoint, returnValue" pointcut-ref="pointcut1" method="after" />
</aop:aspect>
</aop:config>
<bean id="aspect1" class="com......aspectclass" />
Run Code Online (Sandbox Code Playgroud)
我的问题是如何指定在一个以上的不同包装的表达(*包1. ..(..))**.
现在我宣布为每个包在一个方面的一个单独的一个单独的切入点aop:before,并aop:after为每个切入点条目.但我认为这应该是定义多个包切入点的理想方式.
我有以下看点
@Around("execution(public * (@DisabledForBlockedAccounts *).*(..))" + " && @annotation(denyForTeam)")
public Object translateExceptionsDenySelectedAccount(ProceedingJoinPoint pjp, Deny deny) throws Throwable
{
Account account = (Account) pjp.getArgs()[0];
Account selectedAccount = (Account) pjp.getArgs()[1];
if (ArrayUtils.contains(deny.value(), account.getRole()))
{
if (account.getType().equals(Type.CHEF) && !selectedAccount.getType().equals(Type.CHEF))
{
throw new IllegalAccessException("");
}
}
return pjp.proceed();
}
Run Code Online (Sandbox Code Playgroud)
和这个注释:
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface DenyForTeam
{
Role[] value();
}
Run Code Online (Sandbox Code Playgroud)
我得到错误:错误引用的类型不是注释类型:denyForTeam
为什么DenyForTeam没有注释?它标有@interface
我正在尝试使用Spring AOP和Spring MVC Controller.我有3个方面,并希望按特定顺序.为了做到这一点,我使用Ordered接口并实现getOrder方法:
@Aspect
@Component
public class LoggingAspect implements Ordered{
public int getOrder() {
System.out.println("Abra");
return 1;
}
Run Code Online (Sandbox Code Playgroud)
建议课程:
@Component
@Controller
public class HomeController {
Run Code Online (Sandbox Code Playgroud)
切入点:
@Aspect
public class SystemArchitecture {
@Pointcut("execution (* com.jajah.StorageManager.HomeController.*(..))")
public void inHomeController(){}
@Pointcut("execution (* com.jajah.StorageManager.HomeController.*(..))")
public void loggable(){}
@Pointcut("execution (* com.jajah.StorageManager.HomeController.*(..))")
public void authenticated(){}
}
Run Code Online (Sandbox Code Playgroud)
组态:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<annotation-driven />
<context:annotation-config />
<aop:aspectj-autoproxy proxy-target-class="false"/>
<beans:bean id="AuthenticationAspect" class="com.jajah.CommonAspects.SecurityAspects.OAuthAspect"/>
<beans:bean id="ErrorHandlingAspect" …Run Code Online (Sandbox Code Playgroud) 我知道围绕控制器方法编写AOP建议的标准方法,并且如果在控制器方法中声明,则可以访问HttpServletRequest arg.
但我的情况是我有一个翻译服务,目前是会话范围的维护用户的翻译区域设置.我觉得这使得服务状态有限,而且我不希望它是会话范围的,因为我认为它确实是Singleton.但是有多个地方调用了翻译服务方法,因此我不想更改签名以在这些方法中添加请求/语言环境.问题是翻译服务方法的所有调用者都无法访问HttpServletRequest(不是控制器方法)?我是否可以围绕翻译服务方法编写一个方面,并以某种方式神奇地访问HttpServletRequest,无论它是否在调用者的上下文中可用?
@Service
public class TranslationService {
public void translate(String key) {
...
}
}
@Aspect
@Component
public class LocaleFinder {
@PointCut("execution(* TranslationService.translate(..))")
private void fetchLocale() {}
@Around("fetchLocale()") // in parameter list
public void advice(JoinPoint joinpoint, HttpServletRequest request) { .... }
}
Run Code Online (Sandbox Code Playgroud)
如果现在,translate的调用者没有HttpServletRequest,我不能在建议中得到请求吗?有解决方法吗?
Say Service调用需要应用日志方面(注释)的Dao类.我想知道方面实际上是如何应用的.
根据我在服务对象下注入DAO时的理解,spring发现有一些方面(在这种情况下是日志记录)是为DAO配置的,因此它会注入代理对象而不是实际的目标对象.现在,当对DAO中的任何方法进行实际调用时,代理应用方面,然后调用实际的目标对象.那是对的吗 ?另外我相信这叫做跑步编织.
另一方面,可以使用加载时间编织(使用javaagent配置)完成相同的操作,其中对需要应用方面的类执行字节代码操作.所以代理不会在这里出现.
如果我错了,请纠正我,因为这是所有弹簧模块的基础?
在使用Spring AOP执行之前,是否可以在某些检查的基础上更改方法参数值
我的方法
public String doSomething(final String someText, final boolean doTask) {
// Some Content
return "Some Text";
}
Run Code Online (Sandbox Code Playgroud)
建议方法
public Object invoke(final MethodInvocation methodInvocation) throws Throwable {
String methodName = methodInvocation.getMethod().getName();
Object[] arguments = methodInvocation.getArguments();
if (arguments.length >= 2) {
if (arguments[0] instanceof String) {
String content = (String) arguments[0];
if(content.equalsIgnoreCase("A")) {
// Set my second argument as false
} else {
// Set my second argument as true
}
}
}
return methodInvocation.proceed();
}
Run Code Online (Sandbox Code Playgroud)
请建议我设置方法参数值的方法,因为参数没有setter选项.