Spring中同一个类方法互调时注解失效 泛型的重要性

记录两个问题

  1. springboot中@Async或者@Transactional注解的方法要想起作用,则最后执行的实例一定是spring生成的动态代理对象。所以在一个类中方法互调时,被调用的那个方法上的对应注解并不会起作用
@Service  
public class PersonServiceImpl implements PersonService {  

 @Autowired  
 PersonDao personDao;  

 @Override  
 @Transactional  
 public boolean addPerson(Person person) {  
  	boolean result = personDao.insertPerson(person)>0 ? true : false;  
 	return result;  
 }  

 	@Override  
 	//@Transactional  
 public boolean updatePersonByPhoneNo(Person person) {  
  	boolean result = personDao.updatePersonByPhoneNo(person)>0 ? true : false;  
  	//同一个类中@Transactional并不起作用
  	addPerson(person); 
 	 return result;  
 }  
} 

Stack Overflow上也有人给出类似的例子,说明注入的都是根据注解生成的代理对象

class Bean2 {

      @Autowire
      private InventoryDisclosureBO idbo;   <-- Spring will inject a proxy here

      public void persist(InventoryDisclosureStatus data) {
           idbo.persist(data);     <-- now it will work via proxy
      }
   }

原因是生成的代理类逻辑如

@Service  
class A{  
    @Transactinal  
    method b(){...}  

    method a(){    //标记1  
        b();  
    }  
}  

//Spring扫描注解后,创建了另外一个代理类,并为有注解的方法插入一个startTransaction()方法:  
class proxy$A{  
    A objectA = new A();  
    method b(){    //标记2  
        startTransaction();  
        objectA.b();  
    }  

    method a(){    //标记3  
        objectA.a();    //由于a()没有注解,所以不会启动transaction,而是直接调用A的实例的a()方法  
    }  
}  
  1. 泛型的作用
    以前一直没正确理解泛型的作用和意义,直到这次另一个部门提供的接口返回值格式是随心所欲,也不按文档来,逼得没办法写了泛型来解析。发现确实好用,重新回去看书理解了下泛型,觉得主要就是能给程序更多的灵活性。

 - 泛型接口
 public interface Generator<T> {
	T next();
	...
 }
 - 泛型类(没什么特别的,多个T占位符而已)
 public class Generator<T> {
 	private T field;
	piblic T get (){return a;} 
	//泛型方法 (可变参数与泛型的结合)
	public <T> List<T> makeList(T... args){
		List<T> result = new ArrayList<T>();
		for(T item:args)
			result.add(item);
		return result;
	}
	...
 }

注意项:

  • 在泛型代码内部,无法获得有关泛型参数类型的信息。List< String> 和 List< Integer> 在运行时都被擦除成了List类型 。即泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。
  • Java中的泛型这一概念提出的目的,导致其只是作用于代码编译阶段,在编译过程中,对于正确检验泛型结果后,会将泛型的相关信息擦出,也就是说,成功编译过后的class文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段。
  • 类型推断只对赋值操作有效,其他时候并不起作用

作用:构造复杂模型、适配器模式的实现…

  1. 类型通配符
    由于在逻辑上并不能将类似于Box< Number>和Box< Integer>的对象看成是具有父子关系的类型,如果同时又需要一个在逻辑上有继承关系的泛型,就可以用类型通配符来解决。
    比如Box< ?>在逻辑上是所有Box< 类型>的父类
public class GenericTest {

    public static void main(String[] args) {

        Box<String> name = new Box<String>("corn");
        Box<Integer> age = new Box<Integer>(712);
        Box<Number> number = new Box<Number>(314);

        getData(name);
        getData(age);
        getData(number);
    }

    public static void getData(Box<?> data) {
        System.out.println("data :" + data.getData());
    }
}

如果对参数类型有进一步的限制,比如只能是Number及其自雷,这时就需要用到类型通配符上/下限
类型通配符上限通过形如Box<? extends Number>形式定义,相对应的,类型通配符下限为Box<? super Number>形式,其含义与类型通配符上限正好相反

public class GenericTest {

    public static void main(String[] args) {

        Box<String> name = new Box<String>("corn");
        Box<Integer> age = new Box<Integer>(712);
        Box<Number> number = new Box<Number>(314);

        getData(name);
        getData(age);
        getData(number);
        //代码在1处会报错二2,3处正常
        //getUpperNumberData(name); // 1
        getUpperNumberData(age);    // 2
        getUpperNumberData(number); // 3
    }

    public static void getData(Box<?> data) {
        System.out.println("data :" + data.getData());
    }
  
    public static void getUpperNumberData(Box<? extends Number> data){
        System.out.println("data :" + data.getData());
    }
}

参考:
在同一个类中调用其他有注解(如@Async,@Transactianal)的方法,注解失效问题
Java泛型总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值