使用Spring我在注释的Aspect类上进行依赖注入时遇到了一些问题.CacheService是在Spring上下文启动时注入的,但是当编织发生时,它表示cacheService为null.所以我不得不手动重新查看spring上下文并从那里获取bean.还有另一种方式吗?
这是我的看点的一个例子:
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import com.mzgubin.application.cache.CacheService;
@Aspect
public class CachingAdvice {
private static Logger log = Logger.getLogger(CachingAdvice.class);
private CacheService cacheService;
@Around("execution(public *com.mzgubin.application.callMethod(..)) &&"
+ "args(params)")
public Object addCachingToCreateXMLFromSite(ProceedingJoinPoint pjp, InterestingParams params) throws Throwable {
log.debug("Weaving a method call to see if we should return something from the cache or create it from scratch by letting control flow move on");
Object result = null;
if (getCacheService().objectExists(params))}{
result = getCacheService().getObject(params);
} else {
result = pjp.proceed(pjp.getArgs()); …Run Code Online (Sandbox Code Playgroud) 我无法理解aspectJ的编译时和加载时编织,并弄清楚要使用什么(以及如何使用ajc)来编译和构建我的项目.
这是我的项目结构: -
TestProject:一个java服务库.其他一些项目正在使用它.该项目不包含任何方面.
TestProject-Aspects:包含
在TestProject中为几个类提供建议的方面.我没有使用
AspectJ5注释样式,我所有的连接点都只是
当前的方法执行.
我的问题:
是否需要编织?
这样的事情会起作用吗?
编译TestProject-Aspects
<iajc>
sourceroots=${sources.dir}
destdir=${classes.dir}
classpath=${standard.compile.classpath}
</iajc>
Run Code Online (Sandbox Code Playgroud)
编译TestProject
<iajc>
sourceroots=${sources.dir}
destdir=${classes.dir}
classpath=${standard.compile.classpath}
inpath=${[TestProject-Aspects]pkg.classpath}
</iajc>
Run Code Online (Sandbox Code Playgroud)
我想用HTTP请求测试我们的REST服务(有点黑盒测试).然而,经过几个小时的谷歌搜索和尝试不同的配置,我仍然无法正确启动Jetty.这是我当前的配置(我尝试了多个不同的版本):
的pom.xml
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.8</version>
<configuration>
<junitArtifactName>junit:junit</junitArtifactName>
<excludes>
<exclude>**/*_Roo_*</exclude>
<exclude>**/*Util*</exclude>
<exclude>**/*IT*</exclude>
</excludes>
<forkMode>once</forkMode>
<argLine>-javaagent:'${settings.localRepository}/org/springframework/spring-instrument/${org.springframework-version}/spring-instrument-${org.springframework-version}.jar' -javaagent:'${settings.localRepository}/org/aspectj/aspectjweaver/${org.aspectj-version}/aspectjweaver-${org.aspectj-version}.jar'</argLine>
<useSystemClassLoader>true</useSystemClassLoader>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.8</version>
<configuration>
<forkMode>once</forkMode>
<argLine>-javaagent:'${settings.localRepository}/org/springframework/spring-instrument/${org.springframework-version}/spring-instrument-${org.springframework-version}.jar' -javaagent:'${settings.localRepository}/org/aspectj/aspectjweaver/${org.aspectj-version}/aspectjweaver-${org.aspectj-version}.jar'</argLine>
<useSystemClassLoader>false</useSystemClassLoader>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.10</version>
<configuration>
<scanintervalseconds>10</scanintervalseconds>
<stopkey>foo</stopkey>
<stopport>9999</stopport>
<contextpath>/${project.artifactId}</contextpath>
<connectors>
<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
<port>9090</port>
</connector>
</connectors>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<scanintervalseconds>0</scanintervalseconds>
<daemon>true</daemon>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution> …Run Code Online (Sandbox Code Playgroud) rest spring integration-testing maven-jetty-plugin load-time-weaving
我使用spring-instrument.jar和AspectJ LTW配置了Spring 3.0.6和:
<context:load-time-weaver aspectj-weaving="on" weaver-class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
Run Code Online (Sandbox Code Playgroud)
从依赖项中删除CGLIB时,即使创建了MyBean(并且运行了@PostConstruct),我也会收到以下异常:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'crawlItemService' defined in file [/path/to/project/foo/bar/MyBean.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:435)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:409)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:541)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:147)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:297)
... 72 more
Caused by: org.springframework.aop.framework.AopConfigException: Cannot proxy …Run Code Online (Sandbox Code Playgroud) 我正在使用Spring 3.0 RC1中的缓存抽象机制:我已经设置了字节码(基于AspectJ),因此缓存机制可以应用于从类本身内部调用的方法.值得一提的是,首先我使用基于代理的方法:一切正常(因为方法是从另一个对象调用的.)
一旦我切换到AspectJ(我激活了LTW,将正确的jar添加到他们的位置 - 一切正常,没有抛出异常),没有发生缓存
有什么建议吗?谢谢.
====以后编辑========
我将日志设置为DEBUG for org.springframework.
如果使用代理模式,我可以清楚地看到消息添加缓存方法'getLargeAssetContent'....其中getLargeAssetContent是我的"可缓存"方法...(请参见下文)
如果使用aspectj模式,我没有看到此消息....每个请求都转到DAO层...其中,在缓存工作的情况下,请求在服务层停止.
我做错了什么?我需要一个aop.xml吗?我没有使用AOP ....所以我还没有aop.xml.
谢谢您的帮助.
*>*2011-12-12 16:38:55,998 DEBUG [org.springframework.cache.annotation.AnnotationCacheOperationSource]
(http-127.0.0.1-8080-6)使用属性添加可缓存方法'getLargeAssetContent':[CacheOperation [public com.mycompany.myprj.model.AssetContent com.mycompany.myprj.dao.jcr.AssetDAOImpl.getLargeAssetContent(java.lang) .string)抛出com.mycompany.myprj.dao.MyPrjPersistenceException] caches = [assets] | condition =''| key ='#nodeId'] 2011-12-12 16:38:56,013 INFO [com.mycompany.myprj.dao.jcr.AssetDAOImpl](http-127.0.0.1-8080-6)获取资产的内容(getLargeAssetContent)来自节点的id = 575d8dc0-01be-41e4-85ce-a654fab97fe8 2011-12-12 16:38:56,092 INFO [com.mycompany.myprj.dao.jcr.AssetDAOImpl](http-127.0.0.1-8080-6)返回来自id = 575d8dc0-01be-41e4-85ce-a654fab97fe8**的节点的资产内容
*
//内容现在被缓存2011-12-12 16:38:57,654 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory](http-127.0.0.1-8080-6)返回单例bean的缓存实例assetController'2011-12-12 16:38:57,654 DEBUG [org.springframework.web.servlet.DispatcherServlet](http-127.0.0.1-8080-6)[/ myprj/asset/get/575d8dc0-的最后修改值01be-41e4-85ce-a654fab97fe8]是:-1 2011-12-12 16:38:57,654 INFO [com.mycompany.myprj.services.AssetService](http-127.0.0.1-8080-6)获取带有id的资产: 57
*
我已将aspectJ方面捆绑到单个War(aspectsWar.war)文件中,并将其部署到具有现有运行应用程序的应用程序服务器,并在tomcat服务器上使用LTW编织与javaagent.
我可以在aspectWar.war上看到拦截调用的方面,但是在同一个jvm上运行的其他应用程序上没有.
有没有办法让我的aspectj方面识别和编织所有其他正在运行的应用程序(最好不必修改单个war文件),可能是通过对app server的一些自定义类加载更改...
注意:这是使用aspectJ本身而没有任何与Spring相关的集成.
请指教.
我将类,接口和枚举的源文件混合在一起,放在一个包中,如下所示:
package com.mycompany.data;
class Dog {
// implementation
}
package com.mycompany.data;
class Cat {
// implementation
}
package com.mycompany.data;
enum Gender {
// gender options
}
package com.mycompany.data;
interface Animal {
// methods
}
// ... plus a lot more concrete classes and a few more interfaces ...
Run Code Online (Sandbox Code Playgroud)
目标:让所有类都实现新的接口和新的方法。
问题:我可以成功地将接口编织到类中,并排除枚举,但是我无法弄清楚如何也不能将新接口添加到包中的接口上。
我的方面目前看起来像:
public aspect SecureAspect {
declare parents: com.mycompany.data.* && !java.lang.Enum+ implements Secure;
// add method from secure interface to everything implementing Secure
}
Run Code Online (Sandbox Code Playgroud)
它匹配Dog,Cat …
不知道出了什么问题,但AOP似乎没有在弹簧启动(v1.1.6)的设置中工作.
@Configuration
@ComponentScan
@EnableJpaRepositories
@EnableTransactionManagement
@EnableAutoConfiguration
@EnableCaching
@EnableLoadTimeWeaving
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Run Code Online (Sandbox Code Playgroud)
而在方面类
@Aspect
public class MyAspect {
@AfterReturning(pointcut = "execution(private * com.myapp.service.MyService.test(..)) && args(str1,str2)", argNames = "str1,str2")
public void advice(String str1, String str2) throws IOException {
System.out.println("Advising after returning");
}
}
Run Code Online (Sandbox Code Playgroud)
在需要建议的服务类中
@Service
public class MyService {
public void test(String str1, String str2) throws IOException {
System.out.println("Test method in service");
//rest of the implementation
}
}
Run Code Online (Sandbox Code Playgroud)
我也有像这样的META-INF/aop.xml
<!DOCTYPE aspectj …Run Code Online (Sandbox Code Playgroud) 我正在编写一个打包为可执行jar文件的spring boot web应用程序,我需要加载时间AspectJ编织.使用-javaagent对我来说不是一个选项,因为它需要我们的DevOps来更改部署工具链,我现在不想处理它.这是我的主课.
@SpringBootApplication
@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public LoadTimeWeaver loadTimeWeaver() {
return new InstrumentationLoadTimeWeaver();
}
}
Run Code Online (Sandbox Code Playgroud)
这没用.我认为注入InstrumentationLoadTimeWeaver嵌入式Tomcat 可能效果不佳.我尝试用它替换它TomcatLoadTimeWeaver.但结果是Spring上下文无法加载以下错误消息.
引起:java.lang.IllegalStateException:无法初始化TomcatLoadTimeWeaver,因为Tomcat API类不可用
spring-boot github问题上的这个错误得出结论,当前AspectJ加载时编织不能与嵌入式tomcat一起使用.我的问题是为什么不可能?我想了解什么是加载时间编织机制,这使得无法在可执行的Spring启动Web jar中工作.
我正在寻找一个更好地理解这个问题.解决方法非常简单,即将配置数据移动到另一个没有包含代理/建议的类,但我认为更好地理解它将帮助我避免将来出现其他相关问题,所以我想要任何解释任何人可以提供.
我正在使用Spring 3.1.0.RELEASE与Spring STS和vFabric tc服务器.使用@Controller类实现了一个基本的小型REST服务器.这是所有伟大的(实际上,它是),但@Controller也@Transactional,并且和负载时编织和TC的vFabric服务器之间,它打破@Value.
@Controller
@RequestMapping("/hello")
public class MyAPI {
@Value("${my.property}")
private String prop;
...
@Transactional
handleRequest(...) ...
}
Run Code Online (Sandbox Code Playgroud)
和属性文件app.properties:
my.property = SUCCESS
Run Code Online (Sandbox Code Playgroud)
这在JUnit下工作正常,测试得到一个支持设置为"SUCCESS"的MyAPI对象.但是当应用程序加载到vFabric中时,我猜它会加载时间编织和代理.无论发生什么事情,有创造了两个MyAPI情况下,一个拥有道具=="成功"和另一个(这是很不幸的是处理HTTP请求中的一个),其中有托=="$ {} my.prop".
总而言之,我称之为魔术的失败,这是我使用像AOP这样的东西最大的担忧.即使使用STS,我也不知道如何找出问题背后的原因,或者弄清楚这是否是一个严重的错误.如果它是一个bug,我不知道它是Spring,AspectJ,加载时织入器还是vFabric中的bug,所以我甚至不知道在哪里提交bug报告.
因此,理解这一点的任何帮助将不胜感激.谢谢.
aspectj ×8
spring ×7
java ×4
aop ×2
spring-aop ×2
spring-boot ×2
tomcat ×2
annotations ×1
caching ×1
cglib ×1
classloader ×1
interface ×1
rest ×1