1.需要处理的问题:如何扫描xml,如何根据包名获取包下的类,如何生成注释?
2.先建立一个核心类
public class SpringAnnotationFramework {
private static List
private static Map
private static List
private static List
private static Map
public SpringAnnotationFramework(String fileName) {
readXml(fileName);
parsePackage();
}
/**
* 读取xml文件
*
* @param fileName
* xml文件的路劲
*/
private void readXml(String fileName) {
SAXReader saxReader = new SAXReader();
try {
URL xmlUrl = this.getClass().getClassLoader().getResource(fileName);
Document document = saxReader.read(xmlUrl);
Map
xMap.put("ns", "http://www.springframework.org/schema/beans");
XPath xPath = document.createXPath("//ns:beans/ns:context_component-scan");
xPath.setNamespaceURIs(xMap);
List
for (Element element : elements) {
String packgeName = element.attributeValue("base-package");
Packages pack = new Packages();
pack.setPackageName(packgeName);
packages.add(pack);
}
// 获取properties文件的xml
XPath uXPath = document.createXPath("//ns:beans/ns:util_properties");
uXPath.setNamespaceURIs(xMap);
List
for (Element element : propElements) {
String pid = element.attributeValue("id");
String location = element.attributeValue("location");
PropertyDefinition pd = new PropertyDefinition();
String fpath = location.split(":")[1];
pd.initProp(fpath);
propertyDefinitions.put(pid, pd);
}
// 解析aop中的xml
XPath configXPath = document.createXPath("//ns:beans/ns:config");
configXPath.setNamespaceURIs(xMap);
List
for (Element element : configElements) {
Config config = new Config();
String flag = element.attributeValue("proxy-target-class");
config.setProxy_target_class(flag);
XPath aspectXPath = document.createXPath("ns:aspect");
aspectXPath.setNamespaceURIs(xMap);
List
for (Element aspectElement : aspectElemnets) {
Aspect aspect = new Aspect();
String id = aspectElement.attributeValue("id");
String ref = aspectElement.attributeValue("ref");
aspect.setId(id);
aspect.setRef(ref);
Object obj = singleton.get(ref);// 切面对象
XPath pointcutXPath = document.createXPath("ns:pointcut");
pointcutXPath.setNamespaceURIs(xMap);
List
for (Element pointcutElement : pointcutElements) {
Pointcut pointcut = new Pointcut();
String pid = pointcutElement.attributeValue("id");
String expression = pointcutElement.attributeValue("expression");
pointcut.setId(pid);
pointcut.setExpression(expression);
aspect.getPonitCutMap().put(pid, pointcut);
}
XPath aroundXPath = document.createXPath("ns:around");
aroundXPath.setNamespaceURIs(xMap);
List
for (Element aroundElement : aroundElements) {
Around around = new Around();
String pointcut_ref = aroundElement.attributeValue("pointcut-ref");
String method = aroundElement.attributeValue("method");
around.setPointcut_ref(pointcut_ref);
around.setMethod(method);
aspect.getAroundMap().put(pointcut_ref, around);
}
config.getAspectMap().put(id, aspect);
configs.add(config);
}
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
/**
* 根据xml得到包路径解析所有得类
*/
private void parsePackage() {
for (Packages p : packages) {
String packageName = p.getPackageName();
for (String name : packageName.split(",")) {
String packagePath = name.replace(".", "/");
packagePath = this.getClass().getClassLoader().getResource(packagePath).getFile();
recurseFile(name, packagePath);
}
}
}
/**
* 根据传过来的类路径,解析得到所有类储存在classes中
*
* @param fname
* 包名
* @param packagePath
* 包路径
*/
private void recurseFile(String fname, String packagePath) {
File dir = new File(packagePath);
if (!dir.exists() || !dir.isDirectory()) {
return;
}
File[] files = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".class");
}
});
for (File file : files) {
if (file.isDirectory()) {
recurseFile(fname + file.getName(), file.getAbsolutePath());
}
try {
String filePath = file.getName().substring(0, file.getName().length() - 6);
Class clazz = Class.forName(fname + "." + filePath);
classes.add(clazz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
/**
* 根据注解初始化所有类
*
* @param clz
*/
public Object InstanceObject(String key) {
for (Class clz : classes) {
Annotation[] annotations = clz.getAnnotations();
boolean flag = clz.isAnnotationPresent(Compnent.class);
if (flag) {
Compnent annotation = (Compnent) clz.getAnnotation(Compnent.class);
String id = annotation.value();
Object obj;
try {
obj = clz.newInstance();
singleton.put(id, obj);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 实例化对象后,给对象中注入内容
InjectionObject();
//查看aop中是否有该类的切面,若有这将次返回值改成代理对象
Object obj=decorateObject1(singleton.get(key));
// 返回对象
return obj;//返回值是obj
}
/**
*
*/
private Object decorateObject1(Object targetObject){
String id = isAspectObject(targetObject);
Object aspectObject = singleton.get(id);
Object proxyObject=null;
if(id!=null){
JDKDynamicProxy proxy=new JDKDynamicProxy();
proxyObject = proxy.getProxyObject(targetObject, aspectObject);
}else{
proxyObject=targetObject;
}
return proxyObject;
}
/**
*
* @param obj 判断该对象是否是要切入的目标对象
* @return
*/
private String isAspectObject(Object obj){
String id=null;
for(Config config:configs){
for(Aspect aspect:config.getAspectMap().values()){
for(Pointcut pointcut:aspect.getPonitCutMap().values()){
String expression = pointcut.getExpression();
String method=expression.split(" ")[0];
String packageName=expression.split(" ")[1].split("[.][.]")[0];
String name = obj.getClass().getPackage().getName();
if(packageName.equals(name)){
id = pointcut.getId();
}
}
}
}
return id;
}
/**
* 获取多利对象
*/
private Object PrototypeInstanceObject(String key, Class clz) {
Object obj = null;
Annotation[] annotations = clz.getAnnotations();
boolean flag = clz.isAnnotationPresent(Compnent.class);
if (flag) {
Compnent annotation = (Compnent) clz.getAnnotation(Compnent.class);
String id = annotation.value();
try {
obj = clz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
return obj;
}
/**
* 初始化所有所有类后,将属性注入类中
*
* @param clz
* 所有实例化得类
*/
private void InjectionObject() {
for (Object obj : singleton.values()) {
Class clz = obj.getClass();
Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
boolean flag = field.isAnnotationPresent(Resource.class);
boolean valueFlag = field.isAnnotationPresent(Value.class);
if (flag) {
Resource annotation = field.getAnnotation(Resource.class);
String name = annotation.name();
Object value = singleton.get(name);
String setMethodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
try {
Method method = clz.getMethod(setMethodName, field.getType());
method.invoke(obj, value);
} catch (Exception e) {
e.printStackTrace();
}
}
if (valueFlag) {
Value annotation = field.getAnnotation(Value.class);
String value = annotation.value();
if (value.contains("#")) {
String result = value.split("[{]")[1].split("[}]")[0];
String id = result.split("[.]")[0];
String key = result.split("[.]")[1];
PropertyDefinition propertyDefinition = propertyDefinitions.get(id);
String propValue = propertyDefinition.getProp(key);
try {
field.setAccessible(true);
field.set(obj, propValue);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
public Object doSingleton(String id) {
return InstanceObject(id);
}
public Object doPrototype(String id, Class clz) {
return PrototypeInstanceObject(id, clz);
}
public boolean isPrototype(Class clazz) {
boolean flag = clazz.isAnnotationPresent(Prototype.class);
return flag;
}
public Object getBean(String id) {
return singleton.get(id);
}
public
Object obj;
if (!isPrototype(clazz)) {
obj = doSingleton(id);
} else {
obj = doPrototype(id, clazz);
}
return (T) obj;
}
}
3.property类加载属性文件
public class PropertyDefinition {
private Properties prop=new Properties();
public void initProp(String classpath){
String path = PropertyDefinition.class.getClassLoader().getResource(classpath).getPath();
try {
prop.load(new FileInputStream(path));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public String getProp(String key){
return prop.getProperty(key);
}
}
4.用于存放解析出来的类名
public class Packages {
private String packageName;
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
}
5.用于处理aop(动态代理)
public class JDKDynamicProxy {
public Object getProxyObject(final Object targetObject,final Object aspectObject){
Object proxyObj=Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
ProceedingJoinPoint pjp=new ProceedingJoinPoint();
pjp.setTargetObject(targetObject);
pjp.setSignation(method);
pjp.setArgs(args);
Method[] methods = aspectObject.getClass().getDeclaredMethods();
Object result=null;
for (Method aspectMethod : methods) {
if("around".equals(aspectMethod.getName())){
result=aspectMethod.invoke(aspectObject, pjp);
}
}
return result;
}
});
return proxyObj;
}
}
6动态代理的一部分
public class ProceedingJoinPoint {
private Method signation;
private Object targetObject;
private Object[] args;
public Object[] getArgs() {
return args;
}
public void setArgs(Object[] args) {
this.args = args;
}
public ProceedingJoinPoint() {
super();
}
public ProceedingJoinPoint(Object targetObject) {
this.targetObject = targetObject;
}
public Method getSignation() {
return signation;
}
public void setSignation(Method signation) {
this.signation = signation;
}
public Object getTargetObject() {
return targetObject;
}
public void setTargetObject(Object targetObject) {
this.targetObject = targetObject;
}
public Object proceed(){
try {
Object returnValue = signation.invoke(targetObject, args);
return returnValue;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException();
}
}
}
7.用于存储around节点
public class Around {
private String pointcut_ref;
private String method;
public String getPointcut_ref() {
return pointcut_ref;
}
public void setPointcut_ref(String pointcut_ref) {
this.pointcut_ref = pointcut_ref;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
}
8.annotation相关
1>Compnent
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Compnent {
public String value();
}
2>Resource
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Resource {
public String name() default "null";
public String value() default "null";
}
3>Value
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Value {
public String value() default "null";
}
4>Prototype
@Target(ElementType.TYPE)
public @interface Prototype {
}