之前写过Java的自定义注解,但是一直没有深入的去研究这个东西。下面就是我这几天研究的心得。
annotation的基础知识我之前的博客有,这里只讲例子:
Annotation注解的定义
类上的注解:
package anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)//类上的注解
@Retention(RetentionPolicy.RUNTIME)//在运行时有效
public @interface TypeAnnotation {
/**
* 类名称注解,默认值为类名称
* @return
*/
public String tableName() default "className";
/**
* 枚举例子
* @author peida
*
*/
public enum EnumClassDemo{BULE,RED,GREEN};
/**
* 枚举例子属性
* @return
*/
EnumClassDemo getEnumClassDemo() default EnumClassDemo.RED;
}
属性上的注解:
package anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)//属性上的注解
@Retention(RetentionPolicy.RUNTIME)//运行时有效
public @interface FiledAnnotation {
/**
* 字段名称注解,默认值为类名称
* @return
*/
public String fileName() default "fileName";
/**
* 枚举例子
* @author peida
*
*/
public enum EnumFiledDemo{BULE,RED,GREEN};
/**
* 枚举例子属性
* @return
*/
EnumFiledDemo getEnumFiledDemo() default EnumFiledDemo.GREEN;
}
注解支持类:
这里特别注意:要实现spring的BeanPostProcessor接口,这个接口里面有两个方法,
一个是实例化bean之前调用的方法postProcessBeforeInitialization,
一个是实例化bean之后调用的方法postProcessAfterInitialization。
可以把解析注解代码,放到之后的方法postProcessAfterInitialization里面,可对bean做一些修改。
package annosupport;
import java.lang.reflect.Field;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import anno.FiledAnnotation;
import anno.TypeAnnotation;
import service.Table;
public class AnnoSupport implements BeanPostProcessor{
public static Table annoImpl() throws Exception{
Class<Table> class1=Table.class;
Table table=class1.newInstance();//返回对象新的实例
if(class1.isAnnotationPresent(TypeAnnotation.class)){//判断类上面是否有注解
TypeAnnotation typeAnnotation=(TypeAnnotation) class1.getAnnotation(TypeAnnotation.class);//得到类注解对象
System.out.println("tableName:"+typeAnnotation.tableName()+"------>getEnumClassDemo:"+typeAnnotation.getEnumClassDemo());
class1.getMethod("setId", String.class).invoke(table, typeAnnotation.tableName());//调用setter方法设置值,id值
}
Field[] fields= class1.getDeclaredFields();//得到所有属性
for (Field field : fields) {
if(field.isAnnotationPresent(FiledAnnotation.class)){//判断字段上面是否有注解
FiledAnnotation filedAnnotation=field.getAnnotation(FiledAnnotation.class);//得到字段注解对象
System.out.println("fileName:"+filedAnnotation.fileName()+"------>getEnumFiledDemo:"+filedAnnotation.getEnumFiledDemo());
class1.getMethod("setName", String.class).invoke(table, filedAnnotation.fileName());//调用setter方法设置值,name值
}
}
return table;
}
/**
* spring bean 实例化之前操作
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
System.out.println("bean实例化之前");
return bean;
}
/**
* spring bean 实例化之后操作
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
System.out.println("bean实例化之后");
try {
bean=annoImpl();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bean;
}
}
配置spring的配置文件
配置包的扫描路径以及位置
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.1.xsd"> <bean id="table" class="service.Table"/><!--把被注解的类交给spring管理--> <bean class="annosupport.AnnoSupport"/><!--注解支持类交给spring管理--> </beans>
被注解的类
package service;
import org.springframework.stereotype.Service;
import anno.FiledAnnotation;
import anno.TypeAnnotation;
import anno.FiledAnnotation.EnumFiledDemo;
import anno.TypeAnnotation.EnumClassDemo;
@TypeAnnotation(tableName="类注解",getEnumClassDemo=EnumClassDemo.BULE)
public class Table {
private String id;
@FiledAnnotation(fileName="字段注解",getEnumFiledDemo=EnumFiledDemo.GREEN)
private String name;
private int age;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
测试例子:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.Table;
public class TestSpring {
public static void main(String[] args) {
try {
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
Table table=(Table) ctx.getBean("table");
System.out.println("id:"+table.getId()+"---->name:"+table.getName());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
bean实例化之后
tableName:类注解------>getEnumClassDemo:BULE
fileName:字段注解------>getEnumFiledDemo:GREEN
id:类注解---->name:字段注解//说明注解成功起作用了,类注解的作用是把tableName值放入id属性中,并创建实例;字段注解是吧filedName值放入name属性当中,并注入实例。
AnnoSupport加上@Service注解交给spring
Table加上@Service注解交给spring
在spring配置文件进行配置:
<context:component-scan base-package="annosupport" />
<context:component-scan base-package="service" />
其余的bean配置可以去掉
直接测试也可以