gpt4 book ai didi

java - 添加 global-method-security 命名空间时,Spring 看不到 @Transactional

转载 作者:搜寻专家 更新时间:2023-11-01 01:54:53 24 4
gpt4 key购买 nike

我创建了一个服务,负责通过 dao 与数据库联系。我用了@Transactional处理事务的注释。

@Service("aclService")
public class HibernateAclServiceImpl implements HibernateAclService{

private final Log logger = LogFactory.getLog(HibernateAclServiceImpl.class);
@Autowired
private AclObjectIdentityDao objectIdentityDao ;
private PermissionFactory permissionFactory = new DefaultPermissionFactory();
@Autowired
private AclCache aclCache;
@Autowired
private PermissionGrantingStrategy grantingStrategy;
@Autowired
private AclAuthorizationStrategy aclAuthorizationStrategy;

private final Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");

@Override
@Transactional
public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
AclObjectIdentity aclObjectIdentity = objectIdentityDao
.get((Long) parentIdentity.getIdentifier());
List<ObjectIdentity> list = new ArrayList<ObjectIdentity>(
aclObjectIdentity.getChildren().size());
for (AclObjectIdentity aoid : aclObjectIdentity.getChildren()) {
final ObjectIdentity oid = new ObjectIdentityImpl(aoid.getObjectClass().getClazz());
list.add(oid);
}
return list;
}

@Override
@Transactional
public Acl readAclById(ObjectIdentity object) throws NotFoundException {
final Map<ObjectIdentity, Acl> objects = readAclsById(Arrays.asList(object), null);
return objects.get(object);
}

@Override
@Transactional
public Acl readAclById(ObjectIdentity object, List<Sid> sids)
throws NotFoundException {
Map<ObjectIdentity, Acl> objects = readAclsById(Arrays.asList(object), sids);
return objects.get(object);
}


@Override
@Transactional
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects)
throws NotFoundException {
return readAclsById(objects, null);
}

@Override
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects,
List<Sid> sids) throws NotFoundException {
Map<ObjectIdentity, Acl> result = new HashMap<ObjectIdentity, Acl>();
Set<Long> objectsToLoad = new HashSet<Long>();

for (int i = 0; i < objects.size(); i++) {
final ObjectIdentity oid = objects.get(i);
boolean aclFound = false;

if (result.containsKey(oid)) {
aclFound = true;
}

if (!aclFound) {
Acl acl = aclCache.getFromCache(oid);

if (acl != null) {
if (acl.isSidLoaded(sids)) {
result.put(acl.getObjectIdentity(), acl);
aclFound = true;
} else {
throw new IllegalStateException(
"Error: SID-filtered element detected when implementation does not perform SID filtering "
+ "- have you added something to the cache manually?");
}
}
}
if (!aclFound) {
objectsToLoad.add((Long) oid.getIdentifier());
}
}

if (objectsToLoad.size() > 0) {
lookupAcl(result, objectsToLoad);
}
return result;
}
public void lookupAcl(Map<ObjectIdentity, Acl> map, Set<Long> objects){
final List<AclObjectIdentity> aoids = objectIdentityDao.getList(objects);
final Map<Long, Long> parents = new HashMap<Long, Long>();
for(AclObjectIdentity aoid : aoids){
if(aoid.isEntriesInheriting()){
parents.put(aoid.getId(), aoid.getParent().getId());
}
}
if(parents.size() > 0){
lookupAcl(map, (Set<Long>)parents.values());
}
for(AclObjectIdentity aoid : aoids){
if(map.containsKey(aoid.getId()))
continue;
final Acl parentAcl = map.get(parents.get(aoid.getId()));
final Acl acl = new AclImpl(new ObjectIdentityImpl(aoid.getObjectClass().getClazz(), aoid.getId()), aoid.getId(), aclAuthorizationStrategy, grantingStrategy, parentAcl, null, aoid.isEntriesInheriting(), new PrincipalSid(aoid.getOwnerSid().getSid()));



List<AccessControlEntryImpl> aces = new ArrayList<AccessControlEntryImpl>(aoid.getAclEntries().size());
for(AclEntry aclEntry : aoid.getAclEntries()){
final Permission permission = permissionFactory.buildFromMask(aclEntry.getMask());
aces.add(new AccessControlEntryImpl(aclEntry.getId(), acl, new PrincipalSid(aclEntry.getSid().getSid()), permission, aclEntry.isGranting(), aclEntry.isAuditSuccess(), aclEntry.isAuditFailure()));
}
setAces((AclImpl) acl, aces);
aclCache.putInCache((AclImpl) acl);
}
}

private void setAces(AclImpl acl, List<AccessControlEntryImpl> aces) {
try {
fieldAces.set(acl, aces);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not set AclImpl entries", e);
}
}

这是我的“app-context.xml”文件的一部分

<security:global-method-security  pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler" />
</security:global-method-security>
<bean id="expressionHandler"
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator" ref="permissionEvaluator" />
<property name="roleHierarchy" ref="roleHierarchy" />
</bean>

<bean class="org.springframework.security.acls.AclPermissionEvaluator"
id="permissionEvaluator">
<constructor-arg ref="aclService" />
</bean>

现在,当我调用服务的功能时,例如。从 Controller 它抛出一个错误 org.hibernate.HibernateException: No Session found for current thread .但是当我发表评论时,一切都很好(交易没有问题)

<security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler" />
</security:global-method-security>

我检查了所有内容,并将有问题的代码缩小到上述部分。有谁知道为什么会这样?

最佳答案

我不确定 global-method-security 是如何在幕后实现的,但是 BeanPostProcessors 有一个鲜为人知的副作用 - 任何直接引用的 bean由 BeanPostProcessor 或由 BPP 引用的内容引用,不符合 AOP 自动代理的条件:

BeanPostProcessors and AOP auto-proxying

Classes that implement the BeanPostProcessor interface are special and are treated differently by the container. All BeanPostProcessors and beans that they reference directly are instantiated on startup, as part of the special startup phase of the ApplicationContext. Next, all BeanPostProcessors are registered in a sorted fashion and applied to all further beans in the container. Because AOP auto-proxying is implemented as a BeanPostProcessor itself, neither BeanPostProcessors nor the beans they reference directly are eligible for auto-proxying, and thus do not have aspects woven into them.

For any such bean, you should see an informational log message: “Bean foo is not eligible for getting processed by all BeanPostProcessor interfaces (for example: not eligible for auto-proxying)”.

(source)

这意味着如果您在引用 BeanPostProcessor 加载的 bean 中有 @Transactional,则实际上会忽略该注释。

解决方案通常是,如果您需要在必须参照 BeanPostProcessor 加载的 bean 中执行事务行为,则您需要使用非 AOP 事务定义 - 即使用 TransactionTemplate。

您可以将 org.springframework 记录器的日志记录打开到 DEBUG 并验证是否正在为您的 aclService bean 输出此消息。

关于java - 添加 global-method-security 命名空间时,Spring 看不到 @Transactional,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12608212/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com