首先
非常重要的一个网址
http://o7planning.org/web/fe/default/en/document/6864/osgi-and-aspectj-integration
里面记录了 eclipse 实现 aspectj切面工程的DEMO~~
这里面使用的是 eclipse 的 equinox框架。
但是我们需要做的WEB项目,使用的是SPRING DM~
进入主题:
1、创建log bundle
2、添加依赖~
这里面需要 aspectj.weaver和runtime,缺哪个都不行。
然后就是cglib和asm了,asm其实代码中没体现,只是因为如果cglib是2.2的话,那必须要有asm 2.2.3,除非cglib 是2.1.3版本。
这里要注意的是~这些JAR全是OSGI版本哦~~~
是不是找不到 OSGI版本的JAR。其实可以加载几个maven仓库~专门提供OSGI版本的库,setting.xml
如下:
<span style="font-family:Microsoft YaHei;font-size:14px;"><?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository>E:/maven_repo</localRepository>
<pluginGroups>
</pluginGroups>
<proxies>
</proxies>
<servers>
<server>
<id>tomcat</id>
<username>admin</username>
<password>admin</password>
</server>
</servers>
<mirrors>
</mirrors>
<profiles>
<profile>
<id>myself</id>
<repositories>
<!-- 设定仓库(repo1.maven.org/maven2/为中央仓库) -->
<repository>
<id>offical</id>
<name>Maven Official Repository</name>
<url>http://repo1.maven.org/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>sonatype</id>
<name>Sonatype Repository</name>
<url>http://repository.sonatype.org/content/groups/public/</url>
</repository>
<repository>
<id>com.springsource.repository.libraries.release</id>
<name>SpringSource Enterprise Bundle Repository - SpringSource Library Releases</name>
<url>http://repository.springsource.com/maven/libraries/release</url>
</repository>
<repository>
<id>com.springsource.repository.libraries.external</id>
<name>SpringSource Enterprise Bundle Repository - External Library Releases</name>
<url>http://repository.springsource.com/maven/libraries/external</url>
</repository>
<repository>
<id>springsource-releases</id>
<name>SpringSource Release Proxy</name>
<url>https://oss.sonatype.org/content/repositories/springsource-releases</url>
</repository>
<repository>
<id>repository.jboss.org-public</id>
<name>JBoss repository</name>
<url>https://repository.jboss.org/nexus/content/groups/public</url>
</repository>
<repository>
<id>eclipse.virgo.build.bundles.release</id>
<name>Eclipse Virgo Build</name>
<url><span style="color:#ff0000;">http://build.eclipse.org/rt/virgo/maven/bundles/release</span></url>
</repository>
<repository>
<id>com.springsource.repository.bundles.external</id>
<name>SpringSource Enterprise Bundle Repository - External Bundle Releases</name>
<url><span style="color:#ff0000;">http://repository.springsource.com/maven/bundles/external</span></url>
</repository>
</repositories>
<pluginRepositories>
<!-- 设定仓库(repo1.maven.org/maven2/为中央仓库) -->
<pluginRepository>
<id>offical</id>
<name>Maven Official Repository</name>
<url>http://repo1.maven.org/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>jboss-public-repository-group</id>
<url>https://repository.jboss.org/nexus/content/groups/public-jboss</url>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
<pluginRepository>
<id>sun</id>
<name>Sun Repository</name>
<url>http://download.java.net/maven/2/</url>
</pluginRepository>
<pluginRepository>
<id>sonatype</id>
<name>Sonatype Repository</name>
<url>http://repository.sonatype.org/content/groups/public/</url>
</pluginRepository>
<pluginRepository>
<id>eclipse.virgo.build.bundles.release</id>
<name>Eclipse Virgo Build</name>
<url><span style="color:#ff0000;">http://build.eclipse.org/rt/virgo/maven/bundles/release</span></url>
</pluginRepository>
<pluginRepository>
<id>com.springsource.repository.bundles.external</id>
<name>SpringSource Enterprise Bundle Repository - External Bundle Releases</name>
<url><span style="color:#ff0000;">http://repository.springsource.com/maven/bundles/external</span></url>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<!-- activeProfiles
| List of profiles that are active for all builds.
|
<activeProfiles>
<activeProfile>alwaysActiveProfile</activeProfile>
<activeProfile>anotherAlwaysActiveProfile</activeProfile>
</activeProfiles>
-->
<activeProfiles>
<activeProfile>myself</activeProfile>
</activeProfiles>
</settings>
</span>
然后是创建切面类~
<span style="font-family:Microsoft YaHei;font-size:14px;">package com.lele.test.helloworld.log;
import org.springframework.stereotype.Component;
//@Aspect
@Component
public class LogAspect {
//@Pointcut("execution(* com.lele.test.helloworld.*.*(..))")
public void anyMethod() {
}
//@Before("anyMethod()")
public void testBefore() {
System.out.println("I can record input params..");
}
//@After("anyMethod()")
public void testAfter() {
System.out.println("I can record input params..,but I'm @After.");
}
//@AfterReturning("anyMethod()")
public void testAfterReturning() {
System.out.println("I can record input params..,but I'm @AfterReturning.");
}
}</span>
切面的注解被注释掉了~原因是之前调试WEB bundle 的时候VIRGO 一直启动报错。所以就改成了 配置<aop:config/>的方式
但是保留了@Component,需要让spring 知道我是一个组件,启动时加载
还要注意的一个地方,就是spring的配置文件applicationContent.xml,我的之前头里没有AOP标签可用,需要加上,而且要注意顺序哦~
这个AOP的bundle 的applicationContent.xml不需要配置什么东西,只有个扫描。
<span style="font-family:Microsoft YaHei;font-size:14px;"><?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="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/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-1.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:component-scan base-package="com.lele.test.helloworld.log"/>
</beans></span>
再就是template.mf文件了。
<span style="font-family:Microsoft YaHei;font-size:14px;">Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: helloworld log module
Bundle-Version: 1.0.0.SNAPSHOT
Bundle-SymbolicName: com.lele.test.helloworld.log
Bundle-Vendor: lele.com
Excluded-Imports: com.lele.test.helloworld.log
Import-Template: org.springframework.*;version="[3.0.5,4)"
Import-Package: org.springframework.context.config;version="[3.0.5,4)",
org.eclipse.gemini.blueprint.config;version="[1.0.0,2)"
<span style="color:#3333ff;">Export-Package: com.lele.test.helloworld.log</span></span>
这行有点不一样<span style="font-family:Microsoft YaHei;font-size:14px;">//DEMO中后面加了东西
</span><pre name="code" class="html"><span style="font-family:Microsoft YaHei;font-size:14px;">Export-Package: com.lele.test.helloworld.log<span style="color:#ff0000;">;aspects=LogAspect</span></span>
加的这个东西,我去掉了也可以执行~没啥问题。
PS:刚试了一下 不要Export-Package都可以执行成功,我有点不相信Eclipse了。。
下面是如何调用这个aspect bundle了。
首先是 web bundle 的 pom.xml
<dependency>
<groupId>com.lele.test.helloworld</groupId>
<artifactId>com.lele.test.helloworld.log</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
没啥说的。。
然后是 spring 的配置文件。搞了2天。。。
<span style="font-family:Microsoft YaHei;font-size:14px;"> <!-- 打开包扫描,将Controller加入到Spring管理中 -->
<context:component-scan base-package="com.lele.test.helloworld.web" />
<!-- 启用AspectJ对Annotation的支持 -->
<!-- <aop:aspectj-autoproxy /> -->
<aop:config>
<aop:aspect ref="logAspect">
<span style="color:#ff0000;"><aop:pointcut id="allMethod" expression="execution(* com.lele.test.helloworld.web.*.s(..))"/></span>
<aop:before pointcut-ref="allMethod" method="testBefore"/>
</aop:aspect>
</aop:config>
<bean id="logAspect" class="com.lele.test.helloworld.log.LogAspect" />
<span style="white-space:pre"> </span>...</span>
这行存在一个问题,就是如果我把最后的s换成*的话,程序会报错:
<span style="font-family:Microsoft YaHei;font-size:14px;">Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'conversionService' defined in ServletContext resource [/WEB-INF/hello-servlet.xml]: Initialization of bean failed; nested exception is java.lang.IllegalStateException: Expecting raw type, not: org.springframework.beans.factory.FactoryBean
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)</span>
未完待续。。。遇到点小问题。
2015-03-21~继续
昨天遇到一点小问题,主要就是这个expression表达式问题。
写成:
<aop:pointcut id="allMethod" expression="execution(* com.lele.test.helloworld..*.*(..))"/>
<aop:pointcut id="allMethod" expression="execution(* com.lele.test.helloworld.web.*.*(..))"/>
<aop:pointcut id="allMethod" expression="execution(* com.lele.test.helloworld.web..*.*(..))"/>
<span style="white-space:pre"> </span>
报错:
Caused by: java.lang.IllegalStateException: Expecting raw type, not: org.springframework.beans.factory.FactoryBean
写成
<aop:pointcut id="allMethod" expression="execution(* com.lele.test.helloworld.web..*.s(..))"/>
成功,查询了一下具体的原因,
是因为 配置了
<!-- 配置这个conversionService,会导致 execution(* com.lele.test.helloworld.web..*.*(..)) 报错-->
<!-- <bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />
-->
然后是 template.mf
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: helloworld web module
Bundle-Version: 1.0.0.SNAPSHOT
Bundle-SymbolicName: com.lele.test.helloworld.web
Bundle-Vendor: lele.com
Import-Template: org.springframework.*;version="[3.0.5,4)",
org.eclipse.virgo.*;version="[3.5.0,4)"
Import-Package: org.springframework.context.config;version="[3.0.5,4)",
org.springframework.web.servlet.config;version="[3.0.5,4)",
org.springframework.aop;version="[3.0.5,4)",
org.springframework.aop.framework;version="[3.0.5,4)",
org.aopalliance.aop;version="1.0.0",
com.lele.test.helloworld.log,
net.sf.cglib.proxy,
net.sf.cglib.core,
net.sf.cglib.reflect,
org.eclipse.virgo.web.dm
Excluded-Imports: com.lele.test.helloworld.web
Snap-Host: com.lele.test.helloworld.host;version="1.0.0.SNAPSHOT"
Snap-ContextPath: /hello
OK~启动~~~~~~
(上面换成了around)
{Around}Before target class is com.lele.test.helloworld.web.HelloworldController@31b70e1e
{Around}Before method:s
{Around}Before input params is aaa
{Around}Before input params is org.apache.catalina.connector.ResponseFacade@68ffed11
然后再来配置service的AOP
template.mf
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: helloworld say module
Bundle-Version: 1.0.0.SNAPSHOT
Bundle-SymbolicName: com.lele.test.helloworld.say
Bundle-Vendor: lele.com
Excluded-Imports: com.lele.test.helloworld.say
Import-Template: org.springframework.*;version="[3.0.5,4)"
Import-Package: org.springframework.context.config;version="[3.0.5,4)",
org.springframework.aop;version="[3.0.5,4)",
org.springframework.aop.framework;version="[3.0.5,4)",
org.aopalliance.aop;version="1.0.0",
com.lele.test.helloworld.log,
net.sf.cglib.proxy,
net.sf.cglib.core,
net.sf.cglib.reflect,
org.eclipse.gemini.blueprint.config;version="[1.0.0,2)"
applicationContent.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/utils"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="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/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-1.2.xsd">
<context:component-scan base-package="com.lele.test.helloworld.say"/>
<!--
<aop:config>
<aop:aspect ref="logAspect">
<aop:pointcut id="allMethod" expression="execution(* com.lele.test.helloworld..*.*(..)) "/>
<aop:around pointcut-ref="allMethod" method="testAround"/>
</aop:aspect>
<aop:pointcut id="logAspect" expression="execution(* com.lele.test.helloworld.*.*(..)"/>
</aop:config>
<bean id="logAspect" class="com.lele.test.helloworld.log.LogAspect" /> -->
<osgi:service ref="helloworld" interface="com.lele.test.helloworld.api.Helloworld"/>
</beans>
AOP的配置被注释掉了~因为WEB bundle里已经配置了。
别忘了POM.XML引入log bundle
ok~~~~编译~启动~
{Around}Before target class is com.lele.test.helloworld.web.HelloworldController@31b70e1e
{Around}Before method:s
{Around}Before input params is aaa
{Around}Before input params is org.apache.catalina.connector.ResponseFacade@68ffed11
{Around}Before target class is com.lele.test.helloworld.say.HelloWorldImpl@3cb70bf2
{Around}Before method:sayHello
{Around}Before input params is aaa
{Around}Before input params is helloworld
{Around}After method:sayHello result:this is aaa ,I can say helloworld
this is aaa ,I can say helloworld
{Around}After method:s result:null
搞定了~~~~~
后面就是慢慢完善了。~
需要DEMO的同学可以留言~~~~
2015-03-21 21:10 补充说明,
WEB中配置ASPECTJ后,service中可不引用LOG bundle(template.mf中一定要写import,否则无法加载到AOP)
DEMO里用的System.out.println()是可以在web 和 service bundle上工作的,但是换成LOG4J就只有WEB bundle的日志输出了。
可能是因为 我的 项目结构是 WEB >-api<-Service 导致依赖无法传递。