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 导致依赖无法传递。








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