首先
非常重要的一個網址
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 導致依賴無法傳遞。