如果我在Spring bean中的私有方法上有@Transactional -annotation,那么注释是否有效?
如果@Transactional注释是在公共方法上,则它可以工作并打开事务.
public class Bean {
public void doStuff() {
doPrivateStuff();
}
@Transactional
private void doPrivateStuff() {
}
}
...
Bean bean = (Bean)appContext.getBean("bean");
bean.doStuff();
Run Code Online (Sandbox Code Playgroud) 我尝试使用Spring 3.x的以下代码失败了BeanNotFoundException,它应该根据我之前问过的问题的答案 - 我可以使用Spring注入相同的类吗?
@Service
public class UserService implements Service{
@Autowired
private Service self;
}
Run Code Online (Sandbox Code Playgroud)
自从我用Java 6尝试这个以来,我发现以下代码工作正常:
@Service(value = "someService")
public class UserService implements Service{
@Resource(name = "someService")
private Service self;
}
Run Code Online (Sandbox Code Playgroud)
但我不明白它如何解决循环依赖.
编辑:
这是错误消息.OP在其中一个答案的评论中提到它:
由以下原因引起:org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖项找到类型为[com.spring.service.Service]的匹配bean:期望至少有一个bean可以作为此依赖项的autowire候选者.依赖注释:{@ org.springframework.beans.factory.annotation.Autowired(required = true)}
ABC.java中定义了两种方法
public void method1(){
.........
method2();
...........
}
public void method2(){
...............
...............
}
Run Code Online (Sandbox Code Playgroud)
我想有AOP上的呼叫方法2.所以,我创建了一个类,AOPLogger.java,具有在方法提供方面功能的checkAccess
在配置文件中,我不喜欢的东西下面
<bean id="advice" class="p.AOPLogger" />
<aop:config>
<aop:pointcut id="abc" expression="execution(*p.ABC.method2(..))" />
<aop:aspect id="service" ref="advice">
<aop:before pointcut-ref="abc" method="checkAccess" />
</aop:aspect>
</aop:config>
Run Code Online (Sandbox Code Playgroud)
但是当调用我的method2时,不会调用AOP功能,即不会调用checkAccess方法的AOPLogger类.
我错过了什么?
我最近注意到,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函数,例如检查是否是否是该函数的首次调用。该课程是代理吗?这取决于定义。您可能会说这是一个使用真实对象继承的代理,而不是使用组合包装。
总而言之,从这里给出的答案中,我了解到这是两种完全不同的机制。为什么做出这些设计选择是另一个悬而未决的问题。
我正在尝试使用千分尺注释应用普罗米修斯指标@Timed。我发现它们只适用于控制器端点,而不适用于“简单”的公共和私有方法。
给出这个例子:
@RestController
public class TestController {
@GetMapping("/test")
@Timed("test-endpoint") //does create prometheus metrics
public String test() {
privateMethod();
publicMethod();
return "test";
}
@Timed("test-private") //does NOT create prometheus metrics
private void privateMethod() {System.out.println("private stuff");}
@Timed("test-public") //does NOT create prometheus metrics
public void publicMethod() {System.out.println("public stuff");}
}
Run Code Online (Sandbox Code Playgroud)
创建以下指标:
...
# HELP test_endpoint_seconds
# TYPE test_endpoint_seconds summary
test_endpoint_seconds_count{class="com.example.micrometerannotationexample.TestController",exception="none",method="test",} 1.0
test_endpoint_seconds_sum{class="com.example.micrometerannotationexample.TestController",exception="none",method="test",} 0.0076286
# HELP test_endpoint_seconds_max
# TYPE test_endpoint_seconds_max gauge
test_endpoint_seconds_max{class="com.example.micrometerannotationexample.TestController",exception="none",method="test",} 0.0076286
...
Run Code Online (Sandbox Code Playgroud)
没有找到@Timed("test-private")和 的指标@Timed("test-public"),这是为什么?
注意:我在这个 github thread上读到,Spring …
我有一个与上面提到的相同的场景
Spring @Transaction方法调用同一个类中的方法,不起作用?
我指的是答案#1,我认为这对我的简单pojo类有效,但它没有.在我的情况下,我没有注释@Transaction.它是一个简单的pojo类.如果我在上面的帖子中举例,我希望拦截每个方法adduser以及使用spring aop的addusers.
是否有可能拦截从同一服务调用中调用的方法?我指的是AspectJAwareProxy,它可以解决问题,但并不能解决整个问题.我的意思是我不希望任何东西被添加到我的业务逻辑中.所以我想避免任何编码,除了定义切入点和定义建议.是否有可能使用Java和spring aop?我正在使用CGlib来生成代理.Spring版本是3.0.5.请.
谢谢,Ajay
假设我有一个Repository类.
@Repository
class MyRepository {
@Transactional
void method1 () {
// some logic here
}
void method2 () {
// some logic here
method1();
// some logic here
}
}
Run Code Online (Sandbox Code Playgroud)
在String中可以这样做吗?这是如何工作的?
According this answer
/sf/answers/240083021/
To use @Transactional when I execute local method I did following steps:
added to pom.xml:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.7</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)
replace in context
<tx:annotation-driven transaction-manager="transactionManager"/>
Run Code Online (Sandbox Code Playgroud)
with
<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>
Run Code Online (Sandbox Code Playgroud)
after it I saw
Could not obtain transaction-synchronized Session for current thread
additionally added:
<context:load-time-weaver/>
Run Code Online (Sandbox Code Playgroud)
But when make mvn clean install I see(problem occures when tests try to execute. In my test I up appliction context):
java.lang.IllegalStateException: Failed …Run Code Online (Sandbox Code Playgroud) 我正在尝试测试我的 bean 是否具有正确的验证注释。我正在使用弹簧引导。这是一个测试用例示例:
package com.example.sandbox;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import javax.validation.ConstraintViolationException;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.validation.annotation.Validated;
@SpringBootTest
class ValidationTest {
@Test
void testConstructor() {
TestedBean bean = new TestedBean(null);
assertThatThrownBy(() -> checkIfValidated(bean)).isInstanceOf(ConstraintViolationException.class);
}
@Test
void testSetter() {
TestedBean bean = new TestedBean(null);
assertThatThrownBy(() -> bean.setSomeProperty(null)).isInstanceOf(ConstraintViolationException.class);
}
private void checkIfValidated(@Valid TestedBean bean) {
}
@Validated
class TestedBean {
@NotNull
private String someProperty;
public TestedBean(String someProperty) {
super();
this.someProperty = someProperty;
}
public String getSomeProperty() {
return someProperty; …Run Code Online (Sandbox Code Playgroud) 鉴于此示例代码:
public class MyServiceImpl implements MyService {
@Transactional
public void myTransactionalMethod() {
List<Item> itemList = itemService.findItems();
for (Item anItem : itemList) {
try {
processItem(anItem);
catch (Exception e) {
// dont rollback here
// rollback just one item
}
}
}
@Transactional
public void processItem(Item anItem) {
anItem.setSomething(new Something);
anItem.applyBehaviour();
itemService.save(anItem);
}
}
Run Code Online (Sandbox Code Playgroud)
这是我想要实现的目标:
processItem(anItem);在其中发生异常时才应回滚.myTransactionalMethod应该继续,这意味着for-each应该结束.myTransactionalMethod但不在内processItem(anItem),myTransactionalMethod则应完全回滚.是否存在不涉及手动管理事务(没有注释)的解决方案?
编辑:我正在考虑使用@Transactional(PROPAGATION=REQUIRES_NEW),不知道它是否会在同一个bean中工作.
java ×10
spring ×9
proxy ×2
spring-aop ×2
spring-boot ×2
annotations ×1
aop ×1
aspectj ×1
hibernate ×1
interception ×1
java-ee ×1
maven ×1
metrics ×1
prometheus ×1
transactions ×1
validation ×1