标注在字段或属性的setter方法上使用。
@Autowired
默认是按照byType进行注入的。
@Autowired private PersonDao personDao;
当byType方式找到了多个符合的bean,可以制定byName注解。
@Autowired @Qualifier("personDaoBean") private PersonDao personDao;
@Resource (这个注解属于J2EE的)的标签
默认是按照byName方式注入的。
@Resource(name=“personDaoBean”) private PersonDao personDao;//用于字段上
当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,
当注解标注在属性的setter 方法上,即默认取属性名作为bean名称寻找依赖对象。
注意:如果没有制定name属性。并且按照默认的名称仍然找不到依赖对象。
@Resource注解会byType装配。但一旦指定了name属性,就只能byName装配了
注解控制器类
@Controller public class ProductOptionFieldController { }
注解变量,指定按名称
@Autowired @Qualifier("productOptionFieldService") Private transient ProductOptionFieldServiceImpl productOptionFieldService; @Autowired @Qualifier("baseCodeDAO") private transient BaseCodeDAOImpl baseCodeDAO;
注解变量,按类型
@Autowired Private transient ProductOptionFieldServiceImpl productOptionFieldService;
注解Service的实现类
@Service("baseCodeService") public class BaseCodeServiceImpl extends BaseWithoutAuditLogService implements BaseCodeService { }
注视Service实现类中每一个重写的方法
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, readOnly = true, timeout = 3) public List<BaseCode> queryBaseCode(BaseCode baseCode) { return baseCodeDAO.queryAll(baseCode); }
Spring事务的传播行为
在service类前加上@Transactional,service所有方法需要事务管理。每一个业务方法开始时都会打开一个事务。
Spring默认情况下会对运行期例外(RunTimeException)进行事务回滚。这个例外是unchecked
如果遇到checked意外就不回滚。
如何改变默认规则:
1 让checked例外也回滚:在整个方法前加上 @Transactional(rollbackFor=Exception.class)
2 让unchecked例外不回滚: @Transactional(notRollbackFor=RunTimeException.class)
3 不需要事务管理的(只查询的)方法:@Transactional(propagation=Propagation.NOT_SUPPORTED)
在整个方法运行前就不会开启事务 还可以加上: @Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true),这样就做成一个只读事务,可以提高效率。
各种属性的意义:
REQUIRED:业务方法需要在一个容器里运行。如果方法运行时,已经处在一个事务中,那么加入到这个事务,否则自己新建一个新的事务。
NOT_SUPPORTED:声明方法不需要事务。如果方法没有关联到一个事务,容器不会为他开启事务,如果方法在一个事务中被调用,该事务会被挂起,调用结束后,原先的事务会恢复执行。
REQUIRESNEW:不管是否存在事务,该方法总汇为自己发起一个新的事务。如果方法已经运行在一个事务中,则原有事务挂起,新的事务被创建。
MANDATORY:该方法只能在一个已经存在的事务中执行,业务方法不能发起自己的事务。如果在没有事务的环境下被调用,容器抛出例外。
SUPPORTS:该方法在某个事务范围内被调用,则方法成为该事务的一部分。如果方法在该事务范围外被调用,该方法就在没有事务的环境下执行。
NEVER:该方法绝对不能在事务范围内执行。如果在就抛例外。只有该方法没有关联到任何事务,才正常执行。
NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务 拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。
@Transactional注解的属性说明
属性 |
类型 |
描述 |
|
枚举型: |
可选的传播性设置 |
|
枚举型: |
可选的隔离性级别(默认值:ISOLATION_DEFAULT) |
|
布尔型 |
读写型事务 vs. 只读型事务 |
|
int型(以秒为单位) |
事务超时 |
|
一组 |
一组异常类,遇到时 必须 进行回滚。默认情况下checked exceptions不进行回滚,仅unchecked exceptions(即RuntimeException的子类)才进行事务回滚。 |
|
一组 |
一组异常类名,遇到时 必须 进行回滚 |
|
一组 |
一组异常类,遇到时 必须不 回滚。 |
|
一组 |
一组异常类,遇到时 必须不 回滚 |
注解缓存,该方法返回值放入到缓存当中
@Cacheable public List<BaseCode> queryByCodeType(int codeType) { List<BaseCode> list =baseCodeDAO.selectByCodeType(codeType); return list; }
@Cacheable注解可以用在方法或者类级别。当他应用于方法级别的时候,就是如上所说的缓存返回值了。
当应用在类级别的时候,这个类的所有方法的返回值都将被缓存。
@Cacheable(value = "employee")public class EmployeeDAO { public Person findEmployee(String firstName, String surname, int age) { return new Person(firstName, surname, age); } public Person findAnotherEmployee(String firstName, String surname, int age) { return new Person(firstName, surname, age); }}
@Cacheable注解有三个参数,value是必须的,还有key和condition。第一个参数,也就是value指明了缓存将被存到什么地方。
@Cacheable(value = "employee") public Person findEmployee(String firstName, String surname, int age) { return new Person(firstName, surname, age); }
上面的代码保证findEmployee的返回值Person对象将被存储在"employee"中。
任何存储在缓存中的数据为了高速访问都需要一个key。Spring默认使用被@Cacheable注解的方法的签名来作为key,当然你可以重写key,自定义key可以使用SpEL表达式。
@Cacheable(value = "employee", key = "#surname") public Person findEmployeeBySurname(String firstName, String surname, int age) { return new Person(firstName, surname, age); }
在findEmployeeBySurname()的注解中"#surname"是一个SpEL表达式,他将使用findEmployeeBySurname()方法中的surname参数作为key。
@Cacheable的最后一个参数是condition(可选),同样的,也是引用一个SpEL表达式。但是这个参数将指明方法的返回结果是否被缓存。
@Cacheable(value = "employee", condition = "#age < 25") public Person findEmployeeByAge(String firstName, String surname, int age) { return new Person(firstName, surname, age); }
上面的例子中,只有年龄小于25的时候才被缓存。
在快速看完了如何使用缓存后,我们接下来看看缓存带来的效果。
<A href="http://my.oschina.net/test45" target=_blank rel=nofollow>@Test</A> public void testCache() { Person employee1 = instance.findEmployee("John", "Smith", 33); Person employee2 = instance.findEmployee("John", "Smith", 33); assertEquals(employee1, employee2); }
上面的例子很简单,第一次调用findEmployee,findEmployee方法将被执行,Spring将他的返回值一个person对象存 入缓存。第二次调用findEmployee的时候findEmployee将不被执行,Spring直接将缓存中的数据作为返回值返回。所以 employee1 和employee2引用了同样的对象。
最后总结一下流程,当执行到一个被@Cacheable注解的方法 时,Spring首先检查condition条件是否满足,如果不满足,执行方法,返回;如果满足,在value所命名的缓存空间中查找使用key存储的 对象,如果找到,将找到的结果返回,如果没有找到执行方法,将方法的返回值以key-对象的方式存入value缓存中,然后方法返回。
注解驱动的缓存
@Cacheable:声明一个方法的返回值应该被缓存。
@CacheFlush:声明一个方法是清空缓存的触发器。
@CacheFlush(key="com.isoftstone.ebiz.insurance.app.common.service.impl.BaseCodeServiceImpl.queryByCodeType", isPrefix = true) public void cacheFlushBaseCode() { }