Java自定义注解与spring BeanPostProcessor详解

之前写过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 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的配置文件

配置包的扫描路径以及位置

 

 


               
        
	
        
  

被注解的类

 

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配置文件进行配置:

 

其余的bean配置可以去掉

直接测试也可以

 

你可能感兴趣的:(java,spring)