注解可以用来修饰类,方法,属性等,可以看做是一个特殊的标记,程序在编译或运行时检测到这些标记,从而进行一些特殊的操作。
1、修饰符,注解的修饰符必须是public,不写默认为public
2、关键字@interface
3、注解名称
4、注解内容
例如:
public @interface Service {
String value() default "";
}
元注解可以用来修饰注解
一般注解用到的元注解有两个@Target和@Retention
用来表明该注解可以修饰的类型与范围
ElementType.TYPE
应用于类、接口(包括注解类型)、枚举
ElementType.FIELD
应用于属性(包括枚举中的常量)
ElementType.METHOD
应用于方法
ElementType.PARAMETER
应用于方法的形参
ElementType.CONSTRUCTOR
应用于构造函数
ElementType.LOCAL_VARIABLE
应用于局部变量
ElementType.ANNOTATION_TYPE
应用于注解类型
ElementType.PACKAGE
应用于包
ElementType.TYPE_PARAMETER
1.8版本新增,应用于类型变量)
ElementType.TYPE_USE
1.8版本新增,应用于任何使用类型的语句中
用于生命周期
RetentionPolicy.SOURCE
编译时被丢弃,不包含在类文件中
RetentionPolicy.CLASS
JVM加载时被丢弃,包含在类文件中,默认值
RetentionPolicy.RUNTIME
由JVM 加载,包含在类文件中,在运行时可以被获取到
我们根据以上注解的定义和属性来自我实现@Service@Autowired@Transactional功能
我们将原来的一个转账的demo基础上进行修改(详情:见博客 自定义Ioc/Aop)
我们之前的demo是通过读取beans.xml配置文件,实例化bean,通过类中的set方法,对其属性进行依赖注入,现在我们将通过@Service注解来实现实例化bean和通过@Autowired注解实现依赖注入,最后通过@Transactional注解实现事务控制
@Service
// 作用于类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
String value() default "";
}
@Autowired
// 作用于属性
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowried {
boolean value() default true;
}
@Transactional
// 作用于类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Transactional {
}
我们首先看一下beans.xml文件,对文件中的bean添加@Service注解,然后对beans.xml文件中的property标签对应的属性,添加@Autowired注解并且注释掉对应的set方法
接着在我们要测试的方法对应的类上添加@Transactional注解,用来测试事务管理
例如:
接下来是重点,改造BeanFactory
public class BeanFactory {
public static Map map=new HashMap<>();
// annotation 版本
static {
// 扫描bank文件夹下的类
Reflections reflections = new Reflections("bank");
try{
// 获取带有Service注解的类
Set> typesAnnotatedWith = reflections.getTypesAnnotatedWith(Service.class);
typesAnnotatedWith.forEach(beanService->{
try {
// 实例化对象,并存入map中,以便之后使用
Object o = beanService.newInstance();
// 获取@Service value值,如果没有赋值默认是""
Service annotation = beanService.getAnnotation(Service.class);
String value = annotation.value();
// 判断,如果我们没有为类取别名,就读取类名
if(StringUtils.isEmpty(value)){
String name= beanService.getSimpleName();
// 判断是否是接口实现类,如果是用接口类名作为key,这样如果更换实现类的时候,由于我们使用接口类名作为key,
// 只需要将@service注解到新的实现类上,我们同样可以使用接口类名调用的到,不需要其他操作
Class>[] interfaces = beanService.getInterfaces();
if(interfaces.length>0){
name=interfaces[0].getSimpleName();
}
// 将类名首字母小写,统一key的格式
value=(new StringBuilder()).append(Character.toLowerCase(name.charAt(0))).append(name.substring(1)).toString();
}
if (map.containsKey(value)){
System.out.println("@service注解value命名不能重复");
}else {
// 注入到map中
map.put(value,o);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
// 通过反射获取属性
if(!map.isEmpty()){
for(Map.Entry a: map.entrySet()){
Object value = a.getValue();
Class> aClass = value.getClass();
// 使用反射技术,获取到类的全部属性
Field[] declaredFields = aClass.getDeclaredFields();
for (int i = 0; i
修改动态代理ProxyFactory
@Service
public class ProxyFactory {
@Autowried
TransationManager transationManager;
// jdk动态代理
public Object getJDKProxy(Object object){
// 创建动态代理对象
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
Class> aClass = object.getClass();
if(aClass.isAnnotationPresent(Transactional.class)){
// 使用事务管理注解
try{
// 打印被代理的对象
System.out.println(object.getClass());
// 打印被代理对象的执行方法
System.out.println(method.getName());
// 答应被代理对象的方法参数
for (int i = 0; i aClass = object.getClass();
if(aClass.isAnnotationPresent(Transactional.class)){
try{
// 开启手动提交事务
transationManager.beginTransation();
// 执行方法
Object invoke = method.invoke(object, objects);
// 提交事务
transationManager.commitTransation();
return invoke;
}catch (Exception e){
transationManager.rollbackTransation();
return null;
}
}else{
Object invoke = method.invoke(o, objects);
return invoke;
}
}
});
}
public Object getProxy(Object object){
// 判断走那种动态代理
Class> aClass = object.getClass();
Class>[] interfaces = aClass.getInterfaces();
if(interfaces.length>0){
// 使用jdkProxy动态代理
Object jdkProxy = getJDKProxy(object);
return jdkProxy;
}else {
// 使用cglib动态代理
return getCglib(object);
}
}
}
@Test
public void annotationTest() throws SQLException {
ProxyFactory proxyFactory = (ProxyFactory) BeanFactory.getBean("proxyFactory");
BankService bankService = (BankService) BeanFactory.getBean("bankService");
BankService proxy = (BankService) proxyFactory.getProxy(bankService);
Boolean transfer = proxy.transfer("6029621011001", "6029621011000", 100);
}
回滚成功!