记录两个问题
- 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()方法
}
}
- 泛型的作用
以前一直没正确理解泛型的作用和意义,直到这次另一个部门提供的接口返回值格式是随心所欲,也不按文档来,逼得没办法写了泛型来解析。发现确实好用,重新回去看书理解了下泛型,觉得主要就是能给程序更多的灵活性。
- 泛型接口
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文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段。
- 类型推断只对赋值操作有效,其他时候并不起作用
作用:构造复杂模型、适配器模式的实现…
- 类型通配符
由于在逻辑上并不能将类似于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泛型总结