基于ASM轻量型AOP框架实现

[color=red]Spring AOP 的底层实现是Java Proxy和CGLib,而CGLib的底层实现是ASM.
本示例直接从ASM实现轻量型AOP框架[/color]

[size=large][color=red]1.XSD配置文件约束:[/color][/size]
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://www.youisoft.org/aaop" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.youisoft.org/aaop" elementFormDefault="qualified" version="1.0">
<xs:simpleType name="match">
<xs:restriction base="xs:string">
<xs:enumeration value="dynamic"/>
<xs:enumeration value="exception"/>
<xs:enumeration value="none"/>
<xs:enumeration value="parameter"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="Descriptor">
<xs:choice>
<xs:element name="args" type="Args" minOccurs="0" maxOccurs="1"/>
<xs:element name="pattern" type="xs:string" minOccurs="0" maxOccurs="1"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="Args">
<xs:sequence>
<xs:element name="arg" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="ret" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="exp" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Config">
<xs:sequence>
<xs:element name="service" type="Service" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="config" type="Config"/>
<xs:complexType name="Adapter">
<xs:sequence/>
<xs:attribute name="class" use="optional" type="xs:string"/>
<xs:attribute name="name" use="optional" type="xs:string"/>
</xs:complexType>
<xs:complexType name="Service">
<xs:sequence minOccurs="0">
<xs:element name="adapter" type="Adapter" minOccurs="0" maxOccurs="1"/>
<xs:element name="component" type="Component" minOccurs="1" maxOccurs="1"/>
<xs:element name="method" type="Method" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="class" use="optional" type="xs:string"/>
<xs:attribute name="match" use="optional" default="none" type="match"/>
<xs:attribute name="name" use="optional" type="xs:string"/>
<xs:attribute name="static" use="optional" default="false" type="xs:boolean"/>
<xs:attribute name="style" use="optional" default="return" type="Style"/>
</xs:complexType>
<xs:complexType name="Component">
<xs:sequence>
<xs:element name="method" type="Method" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="class" use="optional" type="xs:string"/>
<xs:attribute name="name" use="optional" type="xs:string"/>
</xs:complexType>
<xs:simpleType name="Style">
<xs:restriction base="xs:string">
<xs:enumeration value="after"/>
<xs:enumeration value="before"/>
<xs:enumeration value="return"/>
<xs:enumeration value="throw"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="Method">
<xs:sequence>
<xs:element name="descriptor" type="Descriptor" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="match" use="optional" default="none" type="match"/>
<xs:attribute name="name" use="optional" type="xs:string"/>
</xs:complexType>
</xs:schema>

[color=red]XML实现例子[/color]

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://www.youisoft.org/aaop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.youisoft.org/aaop xsd/aaop-1.0.xsd ">

<service class="org.youisoft.sample.SampleService"
name="sampleService" style="return">
<component class="org.youisoft.sample.SampleComponent"
name="sampleComponent">
<method name="invoke"></method>
</component>
<method name="sample">
<descriptor>
<args>
<arg>org.youisoft.sample.Request</arg>
<ret>org.youisoft.sample.Response</ret></args></descriptor>
</method>
</service>


</config>


[size=large][color=red]2.配置文件容器及常量:[/color][/size]


package org.youisoft.config;

/**
*
* @author janly
*
*/
public class Configs{
private java.util.List list=new java.util.ArrayList();

/**
*
* @param config
*/
public void setConfig(Config config){
list.add(config);
}

/**
* @return the configs
*/
public Config[] getConfigs() {
return (Config[])list.toArray(new Config[]{});
}


}


package org.youisoft;
/**
*
* @author janly
*
*/
public interface AopStyle{

public final static String STYLE_BEFORE="before";
public final static String STYLE_AFTER="after";
public final static String STYLE_THROW="throw";
public final static String STYLE_RETURN="return";
public final static String MATCH_NONE="none";
public final static String MATCH_DYNAMIC="dynamic";
public final static String MATCH_PARAMETER="parameter";
public final static String MATCH_EXCEPTION="exception";
/**
*
* @param style
*/
public void setStyle(String style);





}



[size=large][color=red]3.配置文件解析:[/color][/size]

package org.youisoft.config;

import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
*
* @author janly
*
*/
public class XmlConfig {
private final static String SERVICE="/config/service";
private final static String METHODADAPTER="/config/service/adapter";
private final static String SERVICEMETHOD="/config/service/method";
private final static String SERVICEPATTERN="/config/service/method/descriptor/pattern";
private final static String SERVICEARG="/config/service/method/descriptor/args/arg";
private final static String SERVICERET="/config/service/method/descriptor/args/ret";
private final static String SERVICEEXP="/config/service/method/descriptor/args/exp";
private final static String COMPONENT="/config/service/component";
private final static String COMPONENTMETHOD="/config/service/component/method";
private final static String COMPONENTPATTERN="/config/service/component/method/descriptor/pattern";
private final static String COMPONENTARG="/config/service/component/method/descriptor/args/arg";
private final static String COMPONENTRET="/config/service/component/method/descriptor/args/ret";
private final static String COMPONENTEXP="/config/service/component/method/descriptor/args/exp";


public static Configs parserXml(org.xml.sax.InputSource inputSource){
final Configs configs=new Configs();

SAXParserFactory saxFactory=SAXParserFactory.newInstance();
saxFactory.setNamespaceAware(true);
try {
javax.xml.parsers.SAXParser saxParser=saxFactory.newSAXParser();

saxParser.parse(inputSource, new DefaultHandler(){
private PathStack ps=new PathStack();
private Config config;
/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
*/
public void characters(char[] ch, int start, int length)
throws SAXException {

if(SERVICEPATTERN.equals(ps.getPath())){
config.getServiceMethod().setPattern(new String(ch,start,length));
}

if(COMPONENTPATTERN.equals(ps.getPath())){
config.getComponentMethod().setPattern(new String(ch,start,length));
}

if(SERVICEARG.equals(ps.getPath())){
config.getServiceMethod().addArg(new String(ch,start,length));
}

if(SERVICERET.equals(ps.getPath())){
config.getServiceMethod().addRet(new String(ch,start,length));
}

if(SERVICEEXP.equals(ps.getPath())){
config.getServiceMethod().addExp(new String(ch,start,length));
}

if(COMPONENTARG.equals(ps.getPath())){
config.getComponentMethod().addArg(new String(ch,start,length));
}

if(COMPONENTRET.equals(ps.getPath())){
config.getComponentMethod().addRet(new String(ch,start,length));
}

if(COMPONENTEXP.equals(ps.getPath())){
config.getComponentMethod().addExp(new String(ch,start,length));
}






}

/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
*/
public void endElement(String uri, String localName, String name)
throws SAXException {
if(SERVICE.equals(ps.getPath())){
configs.setConfig(config);
}
ps.pop();

}

/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
*/
public void startElement(String uri, String localName,
String name, Attributes attributes) throws SAXException {
ps.push(localName);

if(SERVICE.equals(ps.getPath())){
config=new Config();
config.setServiceClassName(attributes.getValue("class"));
config.setServiceName(attributes.getValue("name"));
if(attributes.getValue("style")!=null) config.setStyle(attributes.getValue("style"));
if(attributes.getValue("match")!=null) config.setMatch(attributes.getValue("match"));
if(attributes.getValue("static")!=null) config.setStaticInvoke(new Boolean(attributes.getValue("static")).booleanValue());
}

if(METHODADAPTER.equals(ps.getPath())){
config.setAdapterClassName(attributes.getValue("class"));
config.setAdapterName(attributes.getValue("name"));

}

if(SERVICEMETHOD.equals(ps.getPath())){
config.getServiceMethod().setMethodName(attributes.getValue("name"));
config.getServiceMethod().setMatch(attributes.getValue("match"));

}

if(COMPONENT.equals(ps.getPath())){
config.setComponentClassName(attributes.getValue("class"));
config.setComponentName(attributes.getValue("name"));
}

if(COMPONENTMETHOD.equals(ps.getPath())){
config.getComponentMethod().setMethodName(attributes.getValue("name"));
config.getComponentMethod().setMatch(attributes.getValue("match"));
}


}

/**
*
* @author janly
*
*/
class PathStack extends java.util.Stack{
/**
*
*/
private static final long serialVersionUID = 1L;
private java.util.Stack stack=new java.util.Stack();

public String getPath(){
java.lang.StringBuffer sb=new java.lang.StringBuffer();
for(int i=0;i<stack.size();i++){
sb.append("/");
sb.append(stack.get(i).toString());
}

return sb.toString();

}

/* (non-Javadoc)
* @see java.util.Stack#empty()
*/
public boolean empty() {
// TODO Auto-generated method stub
return stack.empty();
}

/* (non-Javadoc)
* @see java.util.Stack#peek()
*/
public synchronized Object peek() {
// TODO Auto-generated method stub
return stack.peek();
}

/* (non-Javadoc)
* @see java.util.Stack#pop()
*/
public synchronized Object pop() {
// TODO Auto-generated method stub
return stack.pop();
}

/* (non-Javadoc)
* @see java.util.Stack#push(java.lang.Object)
*/
public Object push(Object arg0) {
// TODO Auto-generated method stub
return stack.push(arg0);
}

/* (non-Javadoc)
* @see java.util.Stack#search(java.lang.Object)
*/
public synchronized int search(Object o) {
// TODO Auto-generated method stub
return stack.search(o);
}


}

}


);
} catch (Exception e) {
e.printStackTrace();
}

return configs;
}



}


[size=large][color=red]4.AOP实现,包括方法前拦截,方法返回拦截,异常拦截等:[/color][/size]

package org.youisoft.config;

import java.io.IOException;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.youisoft.AopStyle;
/**
*
* @author janly
*
*/
public class Config {
private String serviceName;
private String serviceClassName;
private String componentClassName;
private String componentName;
private String adapterClassName;
private String adapterName;
private boolean staticInvoke;
private String style=AopStyle.STYLE_RETURN;
private String match=AopStyle.MATCH_NONE;
private final Method serviceMethod=new Method();
private final Method componentMethod=new Method();
private boolean catchValue=false;

/**
* initialise the default method name,method arguments,method return,method exception of component.
*/
public void initServiceComponent(){

//default method name
if(this.getComponentMethod().getMethodName()==null)
this.getComponentMethod().setMethodName(this.getServiceMethod().getMethodName());


if(this.componentMethod.getDescriptor()==null){
for(java.util.Iterator it=this.getServiceMethod().getArgs().iterator();it.hasNext();){
this.getComponentMethod().addArg(it.next().toString());
}

for(java.util.Iterator it=this.getServiceMethod().getRets().iterator();it.hasNext();){
this.getComponentMethod().addRet(it.next().toString());
}
}


if(this.componentMethod.getExceptions().length==0){
for(java.util.Iterator it=this.getServiceMethod().getExps().iterator();it.hasNext();){
this.getComponentMethod().addExp(it.next().toString());
}

}

}


/**
*
* @param data
* @return
*/
public byte[] config(byte[] data){
org.objectweb.asm.ClassReader cr = new org.objectweb.asm.ClassReader(data);
return config(cr);
}

/**
*
* @return
*/
public byte[] config(){
java.io.InputStream is=this.getClass().getClassLoader().getResourceAsStream(Config.this.getServiceClassName().concat(".class"));
org.objectweb.asm.ClassReader cr=null;
try {
cr = new org.objectweb.asm.ClassReader(is);
} catch (IOException e) {
e.printStackTrace();
}

return config(cr);
}


/**
* the main method of AOP.
* first: method of service in configuration match the destination method.
* second: method of component in configuration match the service method.
* @return
*/
private byte[] config(org.objectweb.asm.ClassReader cr){
try{
org.objectweb.asm.ClassWriter cw=new org.objectweb.asm.ClassWriter(cr,ClassWriter.COMPUTE_MAXS);
org.objectweb.asm.ClassAdapter ca=new org.objectweb.asm.ClassAdapter(cw){
public MethodVisitor visitMethod(int arg0, String arg1, String arg2,String arg3, String[] arg4) {
MethodVisitor mv=super.visitMethod(arg0, arg1, arg2, arg3, arg4);
if(mv!=null){
boolean match=false;
if(arg1.equals(serviceMethod.getMethodName())){
if(serviceMethod.getMatch().equals(AopStyle.MATCH_NONE)||
serviceMethod.getMatch().equals(AopStyle.MATCH_DYNAMIC)
){
serviceMethod.setPattern(arg2);
serviceMethod.clearExps();
for(int i=0;arg4!=null&&i<arg4.length;i++){
serviceMethod.addExp(arg4[i]);
}
match=true;
}else if(serviceMethod.getMatch().equals(AopStyle.MATCH_PARAMETER)&&
serviceMethod.getDescriptor().equals(arg2)){
serviceMethod.clearExps();
for(int i=0;arg4!=null&&i<arg4.length;i++){
serviceMethod.addExp(arg4[i]);
}
match=true;
}else if(serviceMethod.getMatch().equals(AopStyle.MATCH_EXCEPTION)&&
serviceMethod.getDescriptor().equals(arg2)){

if(arg4!=null&&serviceMethod.getExceptions().length==arg4.length){
match=true;
for(int i=0;i<arg4.length;i++){
if(!arg4[i].equals(serviceMethod.getExceptions()[i])) match=false;

}
}
}
}


if(match){
if(Config.this.getAdapterClassName()!=null){
try {
Class clazz=Class.forName(Config.this.getAdapterClassName());
if(MethodAdapter.class.isAssignableFrom(clazz)){
java.lang.reflect.Constructor con=clazz.getConstructor(new Class[]{MethodVisitor.class});
mv=(MethodAdapter)con.newInstance(new Object[]{mv});
if(AopStyle.class.isAssignableFrom(clazz)){
((AopStyle)mv).setStyle(Config.this.getStyle());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}else{

if(Config.this.getStyle().equals(AopStyle.STYLE_BEFORE)){

mv=new org.objectweb.asm.MethodAdapter(mv){
/* (non-Javadoc)
* @see org.objectweb.asm.MethodAdapter#visitCode()
*/
public void visitCode() {
if(getServiceComponentMatch()){
Type[] argType=Type.getArgumentTypes(Config.this.getServiceMethod().getDescriptor());
if(Config.this.isStaticInvoke()){
for(int i=1;i<=argType.length;i++){
super.visitVarInsn(argType[i-1].getOpcode(Opcodes.ILOAD), i);
}
super.visitMethodInsn(Opcodes.INVOKESTATIC,Config.this.getComponentClassName(),
Config.this.getComponentMethod().getMethodName(),Config.this.getComponentMethod().getDescriptor());
}else{
super.visitTypeInsn(Opcodes.NEW, Config.this.getComponentClassName());
super.visitInsn(Opcodes.DUP);
super.visitMethodInsn(Opcodes.INVOKESPECIAL,Config.this.getComponentClassName(), "<init>", "()V");

for(int i=1;i<=argType.length;i++){
super.visitVarInsn(argType[i-1].getOpcode(Opcodes.ILOAD), i);
}
super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,Config.this.getComponentClassName(),
Config.this.getComponentMethod().getMethodName(),Config.this.getComponentMethod().getDescriptor());
}

super.visitInsn(Opcodes.POP);

}
super.visitCode();
}

};
}

if(Config.this.getStyle().equals(AopStyle.STYLE_AFTER)){
mv=new org.objectweb.asm.MethodAdapter(mv){


/* (non-Javadoc)
* @see org.objectweb.asm.MethodAdapter#visitInsn(int)
*/
public void visitInsn(int opcode) {
if(opcode>=Opcodes.IRETURN&&opcode<=Opcodes.RETURN){
if(getServiceComponentMatch()){
Type[] argType=Type.getArgumentTypes(Config.this.getServiceMethod().getDescriptor());
if(Config.this.isStaticInvoke()){
for(int i=1;i<=argType.length;i++){
super.visitVarInsn(argType[i-1].getOpcode(Opcodes.ILOAD), i);
}
super.visitMethodInsn(Opcodes.INVOKESTATIC,Config.this.getComponentClassName(),
Config.this.getComponentMethod().getMethodName(),Config.this.getComponentMethod().getDescriptor());
}else{
super.visitTypeInsn(Opcodes.NEW, Config.this.getComponentClassName());
super.visitInsn(Opcodes.DUP);
super.visitMethodInsn(Opcodes.INVOKESPECIAL,Config.this.getComponentClassName(), "<init>", "()V");
for(int i=1;i<=argType.length;i++){
super.visitVarInsn(argType[i-1].getOpcode(Opcodes.ILOAD), i);
}
super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,Config.this.getComponentClassName(),
Config.this.getComponentMethod().getMethodName(),Config.this.getComponentMethod().getDescriptor());

}
super.visitInsn(Opcodes.POP);

}
}
super.visitInsn(opcode);
}

};
}

if(Config.this.getStyle().equals(AopStyle.STYLE_THROW)){
mv=new org.objectweb.asm.MethodAdapter(mv){
private int idx=0;
private java.util.List lList=new java.util.ArrayList();
/* (non-Javadoc)
* @see org.objectweb.asm.MethodAdapter#visitLabel(org.objectweb.asm.Label)
*/
public void visitLabel(Label arg0) {
super.visitLabel(arg0);
if(lList.contains(arg0)&&getServiceComponentMatch()){
Type[] argType=Type.getArgumentTypes(Config.this.getServiceMethod().getDescriptor());
super.visitVarInsn(Opcodes.ASTORE,idx+1);
if(Config.this.isStaticInvoke()){
for(int i=1;i<=argType.length;i++){
super.visitVarInsn(argType[i-1].getOpcode(Opcodes.ILOAD), i);
}
if(catchValue) super.visitVarInsn(Opcodes.ALOAD,idx+1);
super.visitMethodInsn(Opcodes.INVOKESTATIC,Config.this.getComponentClassName(),
Config.this.getComponentMethod().getMethodName(),Config.this.getComponentMethod().getDescriptor());
}else{
super.visitTypeInsn(Opcodes.NEW, Config.this.getComponentClassName());
super.visitInsn(Opcodes.DUP);
super.visitMethodInsn(Opcodes.INVOKESPECIAL,Config.this.getComponentClassName(), "<init>", "()V");

for(int i=1;i<=argType.length;i++){
super.visitVarInsn(argType[i-1].getOpcode(Opcodes.ILOAD), i);
}
if(catchValue) super.visitVarInsn(Opcodes.ALOAD,idx+1);
super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,Config.this.getComponentClassName(),
Config.this.getComponentMethod().getMethodName(),Config.this.getComponentMethod().getDescriptor());
}
super.visitInsn(Opcodes.POP);
super.visitVarInsn(Opcodes.ALOAD,idx+1);
}

}


/* (non-Javadoc)
* @see org.objectweb.asm.MethodAdapter#visitTryCatchBlock(org.objectweb.asm.Label, org.objectweb.asm.Label, org.objectweb.asm.Label, java.lang.String)
*/
public void visitTryCatchBlock(Label arg0, Label arg1,Label arg2, String arg3) {
if(arg2!=null) this.lList.add(arg2);
super.visitTryCatchBlock(arg0, arg1, arg2, arg3);
}


/* (non-Javadoc)
* @see org.objectweb.asm.MethodAdapter#visitVarInsn(int, int)
*/
public void visitVarInsn(int arg0,
int arg1) {
if(arg0>=54&&arg0<=86){
if(arg1>idx) idx=arg1;
}
super.visitVarInsn(arg0, arg1);
}
};
}


if(Config.this.getStyle().equals(AopStyle.STYLE_RETURN)){
mv=new org.objectweb.asm.MethodAdapter(mv){

private int idx=0;
/* (non-Javadoc)
* @see org.objectweb.asm.MethodAdapter#visitVarInsn(int, int)
*/
public void visitVarInsn(int arg0,
int arg1) {
if(arg0>=54&&arg0<=86){
if(arg1>idx) idx=arg1;
}
super.visitVarInsn(arg0, arg1);
}


public void visitInsn(int opcode) {
if(opcode>=Opcodes.IRETURN&&opcode<=Opcodes.RETURN){
if(getServiceComponentMatch()){
Type[] argType=Type.getArgumentTypes(Config.this.getServiceMethod().getDescriptor());
Type retType=Type.getReturnType(Config.this.getServiceMethod().getDescriptor());
if(catchValue) {
super.visitVarInsn(retType.getOpcode(Opcodes.ISTORE),idx+1);
}else{
super.visitInsn(Opcodes.POP);
}

if(Config.this.isStaticInvoke()){
for(int i=1;i<=argType.length;i++){
super.visitVarInsn(argType[i-1].getOpcode(Opcodes.ILOAD), i);
}
if(catchValue) super.visitVarInsn(retType.getOpcode(Opcodes.ILOAD), idx+1);
super.visitMethodInsn(Opcodes.INVOKESTATIC,Config.this.getComponentClassName(),
Config.this.getComponentMethod().getMethodName(),Config.this.getComponentMethod().getDescriptor());
}else{
super.visitTypeInsn(Opcodes.NEW, Config.this.getComponentClassName());
super.visitInsn(Opcodes.DUP);
super.visitMethodInsn(Opcodes.INVOKESPECIAL,Config.this.getComponentClassName(), "<init>", "()V");
for(int i=1;i<=argType.length;i++){
super.visitVarInsn(argType[i-1].getOpcode(Opcodes.ILOAD), i);
}
if(catchValue) super.visitVarInsn(retType.getOpcode(Opcodes.ILOAD), idx+1);
super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,Config.this.getComponentClassName(),
Config.this.getComponentMethod().getMethodName(),Config.this.getComponentMethod().getDescriptor());

}

}
}
super.visitInsn(opcode);
}
};
}
}

}

}
return mv;
}
};
cr.accept(ca, org.objectweb.asm.ClassReader.SKIP_DEBUG);
return cw.toByteArray();
}catch(Exception e){
e.printStackTrace();
return null;
}
}




private boolean getServiceComponentMatch(){
this.initServiceComponent();
boolean match=false;
if(this.getComponentMethod().getMatch().equals(AopStyle.MATCH_NONE)||
this.getComponentMethod().getMatch().equals(AopStyle.MATCH_PARAMETER)){
if(this.getComponentMethod().getDescriptor().equals(this.getServiceMethod().getDescriptor())){
match=true;
}
return match;
}

if(this.getComponentMethod().getMatch().equals(AopStyle.MATCH_DYNAMIC)){
Type[] sargType=Type.getArgumentTypes(Config.this.getServiceMethod().getDescriptor());
Type sretType=Type.getReturnType(Config.this.getServiceMethod().getDescriptor());
Type[] cArgType=Type.getArgumentTypes(Config.this.getComponentMethod().getDescriptor());
if(sargType.length==cArgType.length-1){
if(sretType.toString().equals(cArgType[cArgType.length-1].toString())||
Type.getDescriptor(java.lang.Throwable.class).equals(cArgType[cArgType.length-1].toString())
){
match=true;
catchValue=true;
}

}
return match;
}


if(this.getComponentMethod().getMatch().equals(AopStyle.MATCH_EXCEPTION)){
if(this.getComponentMethod().getDescriptor().equals(this.getServiceMethod().getDescriptor())){
if(this.getComponentMethod().getExceptions().length==this.getServiceMethod().getExceptions().length){
match=true;
for(int i=0;i<this.getComponentMethod().getExceptions().length;i++){
if(!this.getComponentMethod().getExceptions()[i].equals(this.getServiceMethod().getExceptions()[i])) match=false;
}

}
}

return match;
}


return match;
}

/**
*
* @param str
* @param begin
* @param end
* @return
*/
private static String substringBetween(String str,String begin,String end){
int a=str.indexOf(begin);
int b=str.lastIndexOf(end);
return str.substring(a, b);

}

/**
*
* @param str
* @param begin
* @return
*/
private static String substringBefore(String str,String begin){
int a=str.indexOf(begin);
return str.substring(0,a);

}

/**
*
* @param str
* @param end
* @return
*/
private static String substringAfter(String str,String end){
int a=str.indexOf(end);
return str.substring(a+1);

}

/**
*
* @param s
* @param sb
*/
public static void converToSimplePattern(String s,java.lang.StringBuffer sb){
if(s.startsWith("(")) {
converToSimplePattern(substringBetween(s, "(", ")"),sb);
return;
}

if(s.startsWith("[")) {
converToSimplePattern(substringAfter(s,"["),sb);
return;
}

if(s.startsWith("L")){
sb.append("L");
converToSimplePattern(substringAfter(s,";"),sb);
return;
}

if(s!=null&&s.length()>0){
sb.append(s.substring(0,1));
converToSimplePattern(s.substring(1),sb);
return;
}
}

/**
*
* @param s
* @return
*/
public static String converToPattern(String s){
java.lang.StringBuffer sb=new java.lang.StringBuffer("");
if(s.equals("void")) sb.append(Type.getDescriptor(void.class));
if(s.equals("boolean")) sb.append(Type.getDescriptor(boolean.class));
if(s.equals("int")) sb.append(Type.getDescriptor(int.class));
if(s.equals("char")) sb.append(Type.getDescriptor(char.class));
if(s.equals("byte")) sb.append(Type.getDescriptor(byte.class));
if(s.equals("short")) sb.append(Type.getDescriptor(short.class));
if(s.equals("float")) sb.append(Type.getDescriptor(float.class));
if(s.equals("long")) sb.append(Type.getDescriptor(long.class));
if(s.equals("double")) sb.append(Type.getDescriptor(double.class));
if(s.equals("boolean[]")) sb.append(Type.getDescriptor(boolean[].class));
if(s.equals("int[]")) sb.append(Type.getDescriptor(int[].class));
if(s.equals("char[]")) sb.append(Type.getDescriptor(char[].class));
if(s.equals("byte[]")) sb.append(Type.getDescriptor(byte[].class));
if(s.equals("short[]")) sb.append(Type.getDescriptor(short[].class));
if(s.equals("float[]")) sb.append(Type.getDescriptor(float[].class));
if(s.equals("long[]")) sb.append(Type.getDescriptor(long[].class));
if(s.equals("double[]")) sb.append(Type.getDescriptor(double[].class));
if(s.equals("boolean[][]")) sb.append(Type.getDescriptor(boolean[][].class));
if(s.equals("int[][]")) sb.append(Type.getDescriptor(int[][].class));
if(s.equals("char[][]")) sb.append(Type.getDescriptor(char[][].class));
if(s.equals("byte[][]")) sb.append(Type.getDescriptor(byte[][].class));
if(s.equals("short[][]")) sb.append(Type.getDescriptor(short[][].class));
if(s.equals("float[][]")) sb.append(Type.getDescriptor(float[][].class));
if(s.equals("long[][]")) sb.append(Type.getDescriptor(long[][].class));
if(s.equals("double[][]")) sb.append(Type.getDescriptor(double[][].class));

if(!sb.toString().equals("")) return sb.toString();

if(s.endsWith("[][]")) {
sb.append("[[L"+sb.append(substringBefore(s, "[][]")));
}else if(s.endsWith("[]")) {
sb.append("[L"+sb.append(substringBefore(s, "[]")));
}else{
sb.append("L"+s);
}
sb.append(";");

return sb.toString();
}




/**
* @return the serviceName
*/
public String getServiceName() {
return serviceName;
}

/**
* @param serviceName the serviceName to set
*/
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}

/**
* @return the serviceClassName
*/
public String getServiceClassName() {
return serviceClassName;
}

/**
* @param serviceClassName the serviceClassName to set
*/
public void setServiceClassName(String serviceClassName) {
if(serviceClassName!=null) serviceClassName=serviceClassName.replace('.', '/');
this.serviceClassName = serviceClassName;
}

/**
* @return the componentClassName
*/
public String getComponentClassName() {
return componentClassName;
}

/**
* @param componentClassName the componentClassName to set
*/
public void setComponentClassName(String componentClassName) {
if(componentClassName!=null) componentClassName=componentClassName.replace('.', '/');
this.componentClassName = componentClassName;
}

/**
* @return the componentName
*/
public String getComponentName() {
return componentName;
}

/**
* @param componentName the componentName to set
*/
public void setComponentName(String componentName) {
this.componentName = componentName;
}

/**
* @return the style
*/
public String getStyle() {
return style;
}

/**
* @param style the style to set
*/
public void setStyle(String style) {
this.style = style;
}



/**
* @return the adapterClassName
*/
public String getAdapterClassName() {
return adapterClassName;
}


/**
* @param adapterClassName the adapterClassName to set
*/
public void setAdapterClassName(String adapterClassName) {
this.adapterClassName = adapterClassName;
}


/**
* @return the adapterName
*/
public String getAdapterName() {
return adapterName;
}


/**
* @param adapterName the adapterName to set
*/
public void setAdapterName(String adapterName) {
this.adapterName = adapterName;
}



/**
* @return the match
*/
public String getMatch() {
return match;
}


/**
* @param match the match to set
*/
public void setMatch(String match) {
this.match = match;
}


/**
* @return the staticInvoke
*/
public boolean isStaticInvoke() {
return staticInvoke;
}


/**
* @param staticInvoke the staticInvoke to set
*/
public void setStaticInvoke(boolean staticInvoke) {
this.staticInvoke = staticInvoke;
}


/**
* @return the serviceMethod
*/
public Method getServiceMethod() {
return serviceMethod;
}


/**
* @return the componentMethod
*/
public Method getComponentMethod() {
return componentMethod;
}


/**
*
* @author janly
*
*/
class Method{
private String methodName;
private String pattern;
private String match;
private final java.util.List args=new java.util.ArrayList();
private final java.util.List rets=new java.util.ArrayList();
private final java.util.List exps=new java.util.ArrayList();


public void clearExps(){
this.exps.clear();
}

private String convertArgsToPattern(){
if(methodName==null) return null;
if(this.rets.isEmpty()) return null;

java.lang.StringBuffer sb=new java.lang.StringBuffer("(");
for(java.util.Iterator it=this.args.iterator();it.hasNext();){
sb.append(Config.converToPattern(it.next().toString()));
}
sb.append(")");

for(java.util.Iterator it=this.rets.iterator();it.hasNext();){
sb.append(Config.converToPattern(it.next().toString()));
}

return sb.toString();
}

public String[] getExceptions(){
return (String[])this.exps.toArray(new String[]{});
}

boolean addArg(String arg){
return args.add(arg.replace('.', '/'));
}

boolean addRet(String ret){
return rets.add(ret.replace('.', '/'));
}

boolean addExp(String exp){
return exps.add(exp.replace('.', '/'));
}

/**
* @return the pattern
*/
public String getPattern() {
return pattern;
}
/**
* @param pattern the pattern to set
*/
public void setPattern(String pattern) {
this.pattern = pattern;
this.args.clear();
this.rets.clear();
Type[] argsType=Type.getArgumentTypes(pattern);
Type retsType=Type.getReturnType(pattern);
for(int i=0;i<argsType.length;i++){
this.args.add(argsType[i].getClassName());
}
this.rets.add(retsType.getClassName());
}
/**
* @return the methodName
*/
public String getMethodName() {
return methodName;
}
/**
* @param methodName the methodName to set
*/
public void setMethodName(String methodName) {
this.methodName = methodName;
}
/**
* @return the descriptor
*/
public String getDescriptor() {
if(this.pattern!=null) return this.pattern;
return this.convertArgsToPattern();
}

/**
* @return the args
*/
public java.util.List getArgs() {
return args;
}

/**
* @return the rets
*/
public java.util.List getRets() {
return rets;
}

/**
* @return the exps
*/
public java.util.List getExps() {
return exps;
}




/**
* @return the match
*/
public String getMatch() {
if(this.match==null) return Config.this.getMatch();
return match;
}

/**
* @param match the match to set
*/
public void setMatch(String match) {
this.match = match;
}


}

}

[size=x-large][color=red]5.提供WebLogic服务器的实现[/color][/size]

/**
*
*/
package org.youisoft.oracle;
import java.util.Hashtable;
import org.youisoft.config.Config;
import org.youisoft.config.Configs;
import org.youisoft.config.XmlConfig;

import weblogic.utils.classloaders.ClassPreProcessor;

/**
* @author janly
*
*/
public class ServiceClassPreProcessor implements ClassPreProcessor {
private class KeyListMap{
private java.util.Map innerMap=new java.util.HashMap();

/* (non-Javadoc)
* @see java.util.HashMap#put(java.lang.Object, java.lang.Object)
*/
public Object put(Object arg0, Object arg1) {
if(this.innerMap.get(arg0)==null){
java.util.List list=new java.util.ArrayList();
list.add(arg1);
this.innerMap.put(arg0,list);
}else{
((java.util.List)this.innerMap.get(arg0)).add(arg1);
}

return arg1;
}

/* (non-Javadoc)
* @see java.util.HashMap#get(java.lang.Object)
*/
public Object get(Object key) {
return this.innerMap.get(key);
}





}
public final static String XMLCONFIG="youisoft.service.config";


//-Dweblogic.classloader.preprocessor=org.youisoft.oracle.ServiceClassPreProcessor
private KeyListMap serviceMap=new KeyListMap();

/* (non-Javadoc)
* @see weblogic.utils.classloaders.ClassPreProcessor#initialize(java.util.Hashtable)
*/
public void initialize(Hashtable arg0) {


String configFileName=null;
if(arg0!=null&&arg0.get(XMLCONFIG)!=null){
configFileName=arg0.get(XMLCONFIG).toString();
}
if(System.getProperty(XMLCONFIG)!=null){
configFileName=System.getProperty(XMLCONFIG);
}
try{
java.io.FileInputStream fis=new java.io.FileInputStream(configFileName);
org.xml.sax.InputSource inputSource=new org.xml.sax.InputSource(fis);
Configs obj=(Configs)XmlConfig.parserXml(inputSource);
for(int i=0;obj.getConfigs()!=null&&i<obj.getConfigs().length;i++){
this.serviceMap.put(obj.getConfigs()[i].getServiceClassName().replace('/', '.'), obj.getConfigs()[i]);
}
}catch(Exception e){
e.printStackTrace();
}
}

/* (non-Javadoc)
* @see weblogic.utils.classloaders.ClassPreProcessor#preProcess(java.lang.String, byte[])
*/
public byte[] preProcess(String arg0, byte[] arg1) {
if(this.serviceMap.get(arg0)!=null){
try{
java.util.List list=(java.util.List)this.serviceMap.get(arg0);
for(java.util.Iterator it=list.iterator();it.hasNext();){
Config config=(Config)it.next();
arg1=config.config(arg1);
}

}catch(java.lang.Throwable t){

}

}

return arg1;
}


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值