1.使用注解实现ioc的配置
- 定义bean
- bean组件装配,依赖注入
2.面向切面(aop)
- 使用配置文件完成增强
- 使用注解完成增强
1.1 定义bean
<bean id=“xxx” class=“xx.xx.xxx” />
@Component("logger")
public class ServiceLogger {}
@Repository("userDao")
public interface UserDao {}
@Service("userService")
public class UserServiceImpl implements UserService{}
上面代码都完成定义bean,但使用特定的注解可以使组件的用户更加清晰
@Component 用于定义一些额外功能
@Repository 定义Dao层
@Service 定义业务实现
1.2 bean组件装配,依赖注入
/**
* 按类型自动匹配合适的的衣领对象
* 若没有匹配的bean则程序会抛出异常
* 如果依赖不是必须的,设置@Autowired注解的required属性为false可以避免抛出异常
*/
@Autowired
private UserDao userDao;
/**
* Dog类和Cat类继承Pet类,并且分别定义了bean
* 这时通过@Autowired注入会查找到两个bean,程序不知道注入哪一个
* 通过@Qualifier来指定名称注入就可以解决了
*/
@Autowired
private void queryPet(@Qualifier("dog") Pet pet){}
/**
* 比较规范的注解注入
* 通过naeme属性指定名称注入
* 如果没有指定名称,则Resource会根据字段或setter方法产生的默认名称注入,没有找到这根据类型继续匹配
* 字段默认名称字段名
* setter方法默认名称是通过setter方法得到的属性名
*/
@Resource(name = "userDao")
private UserDao userDao;
2.1 使用配置文件完成增强
- 配置文件
/**
* 定义一个Bean
*/
<bean id="logger" class="cn.kgc.springtest2.demo1.logger.ServiceLogger"></bean>
<aop:config>
/**
* 切面,引用上方logger,用来当作增强类
*/
<aop:aspect ref="logger">
/**
* 定义切入点,expression为表达式,语法可以自己收集
* 这里的意思是service包里面的所有类的所有方法都执行此增强
*/
<aop:pointcut id="pointcut" expression="execution(* cn.kgc.springtest2.demo1.service..*(..))"></aop:pointcut>
/**
* 前置增强,目标方法执行前先执行logger里面定义的before()方法
* method="方法名"
* pointcut-ref="切点引用"
*/
<aop:before method="before" pointcut-ref="pointcut"/>
/**
* 后置增强,目标方法正常执行完毕后执行logger里面定义的afterReturn()方法
* 目标方法抛出异常则不会执行此方法
*/
<aop:after-returning method="afterReturn" pointcut-ref="pointcut" returning="result"></aop:after-returning>
/**
* 异常抛出增强,目标方法抛出异常时执行此方法,类似于catch代码块
* throwing=""给目标方法参数赋值
*/
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"></aop:after-throwing>
/**
* 最终增强,类似于finally代码块,不管目标方法如何都会执行此after()方法
*/
<aop:after method="after" pointcut-ref="pointcut"></aop:after>
/**
* 环绕增强,整合了其他增强
*/
<aop:around method="around" pointcut-ref="pointcut"></aop:around>
</aop:aspect>
</aop:config>
- 增强类
public class ServiceLogger{
/**
* 后置增强
* @param joinpoint 执行的方法
* @param result 方法返回结果
*/
public void afterReturn(JoinPoint joinpoint, Object result){
log.info(joinpoint.getTarget()+"执行成功,返回信息是"+result);
}
/**
* 前置增强
*/
public void before(JoinPoint joinPoint){
log.info(joinPoint.getSignature().getName()+"方法即将执行!");
}
/**
* 异常增强
* @param e 发生的异常实例
*/
public void afterThrowing(RuntimeException e){
log.error("我们检测到了报错情况,报错信息如下"+e.getMessage());
}
/**
* 最终增强
*/
public void after(){
log.info("无论上面有没有报错我都会执行");
}
/**
* 环绕增强
* @param jp 执行的方法
*/
public void around(ProceedingJoinPoint jp){
try {
//前置增强 方法执行之前
log.info(jp.getSignature().getName()+"目标方法执行前......");
//通知目标方法执行
Object obj = jp.proceed();
//后置增强 方法执行完毕 (程序发生异常不会执行此语句)
log.info("方法执行完成,方法返回值是"+obj);
} catch (Throwable throwable) {
//异常增强 (程序异常时执行)
log.error("啊报错了!信息是:"+throwable.getMessage());
throwable.printStackTrace();
//不执行finally代码块
//System.exit(0);
} finally {
//最终增强
log.info("我是最终增强!!!!!!");
}
}
}
2.2使用注解完成增强
- 配置文件
<!--开启注解扫描-->
<context:component-scan base-package="cn.kgc"></context:component-scan>
<!--开启注解扫描,扫描切面,增强信息-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
- 增强类
/**
* @Slf4j 事务
* @Aspect 定义切面
* @Component 定义Bean
*/
@Slf4j
@Aspect
@Component
public class ServiceLogger {
/**
* 定义切点
*/
@Pointcut("execution(* cn.kgc.springtest2.demo1.service..*(..))")
public void pointcut(){}
/**
* 通过@AfterThrowing注解定义异常增强
* value 引用切点
* throwing 给参数赋值
*/
@AfterThrowing(value = "pointcut()",throwing = "e")
public void afterThrowing(RuntimeException e){
log.error("我们检测到了报错情况,报错信息如下"+e.getMessage());
}
/**
* 通过@Before定义前置增强
*/
@Before
public void before(JoinPoint joinPoint){
log.info(joinPoint.getSignature().getName()+"方法即将执行!");
}
/**
* 通过@AfterReturning注解定义后置增强
* @param joinpoint 目标方法
* @param result 返回结果
*/
@AfterReturning(value = "pointcut()",returning = "result")
public void afterReturn(JoinPoint joinpoint, Object result){
log.info(joinpoint.getTarget()+"执行成功,返回信息是"+result);
}
/**
* 通过@After定义最终增强
*/
@After("pointcut()")
public void after(){
log.info("无论上面有没有报错我都会执行");
}
/**
* 环绕增强
* @param jp 执行的方法
*/
@Around("pointcut()")
public void around(ProceedingJoinPoint jp){
try {
//前置增强 方法执行之前
log.info(jp.getSignature().getName()+"目标方法执行前......");
//通知目标方法执行
Object obj = jp.proceed();
//后置增强 方法执行完毕 (程序发生异常不会执行此方法)
log.info("方法执行完成,方法返回值是"+obj);
} catch (Throwable throwable) {
//异常增强 (程序异常时执行)
log.error("啊报错了!信息是:"+throwable.getMessage());
throwable.printStackTrace();
//不执行finally代码块
//System.exit(0);
} finally {
//最终增强
log.info("我是最终增强!!!!!!");
}
}
上面只是写了简单的日志增强,还可以添加更复杂的代码来实现其他增强