OSGI 環境下的 AOP 日誌記錄 DEMO 製作過程

首先 

非常重要的一個網址

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>


<aop:pointcut id="allMethod" expression="execution(* com.lele.test.helloworld.*.s(..))"/>
這行存在一個問題,就是如果我把最後的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


引入log bundle~還有cglib的包


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 導致依賴無法傳遞。








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章