spring能够为容器中的对象生成动态代理对象。
动态代理优先
- 被代理对象必须要实现接口,才能产生 代理对象,如果对象没有接口将不能使用动态代理技术
cglib代理(没有接口)
- 第三放代理激素,cglib代理可以对任何类生成代理,代理的原理是对目标对象进行继承代理,如果目标修啊想被final修饰,那么该类无法被cglib代理
aop名词学习
- jointpoint(连接点):目标对象中,所有可以增强的方法
- Pointcut(切入点):目标对象已经增强的方法
- Advice(通知/增强):增强的代码
- Target(目标对象):被代理的对象
- Weaving(织入):将通知应用到切入点的过程
- Proxy(代理):将通知织入到目标对象之后形成的代理对象
- aspect(切面):切入点+通知
基于xml配置
- 准备目标对象
public class UserServiceImpl implements UserService{
@Override
public void save(){
System.out.println("保存用户!");
}
@Override
public void delete(){
System.out.println("删除用户!");
}
@Override
public void update(){
System.out.println("更新用户!");
}
@Override
public void find(){
System.out.println("查找用户!");
}
}
- 准备通知
public class Advice{
//前置通知,目标方法运行之前调用
public void before(){
System.out.println("前置通知!");
}
//后置通知(如果出现异常不会调用),目标方法调用之后调用
public void afterReturning(){
System.out.println("后置通知(异常不会调用)!");
}
//环绕通知,在目标方法之前之后都调用
public Object around(ProceedingJoinPoint pjp){
System.out.println("环绕通知之前!");
Object obj=pjp.proceed();//调用目标方法
System.out.println("环绕通知之后!");
return obj;
}
//异常通知,如果出现异常就会调用
public void afterException(){
System.out.println("出现异常!");
}
//后置通知(无论是否出现异常都会调用),在目标方法运行之后调用
public void after(){
System.out.println("后置通知(出现一场也会调用)!");
}
}
- 配置进行织入,将通知织入目标对象中
<!-- 准备工作:导入aop(约束)命名空间 -->
<!-- 配置目标对象 -->
<bean name="userService" class="com.gjh.service.UserServiceImpl" />
<!-- 配置通知对象 -->
<bean name="advice" class="com.gjh.aop.Advice" />
<aop:config
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* com.gjh.service.*ServiceImpl.*(..))" id="pc" />
<aop:aspect ref="advice">
<aop:before methond="before" pointcut-ref="pc" />
<aop:after-returning methond="afterReturning" pointcut-ref="pc" />
<aop:around methond="around" pointcut-ref="pc" />
<aop:after-throwing methond="afterException" pointcut-ref="pc" />
<aop:after methond="adter" pointcut-ref="pc" />
</aop:aspect>
</aop:config>
注解配置
- 准备目标对象
public class UserServiceImpl implements UserService{
@Override
public void save(){
System.out.println("保存用户!");
}
@Override
public void delete(){
System.out.println("删除用户!");
}
@Override
public void update(){
System.out.println("更新用户!");
}
@Override
public void find(){
System.out.println("查找用户!");
}
}
- 准备通知
@Aspect
//表示这是一个通知类
public class Advice{
@Pointcut("execution(* com.gjh.service.*ServiceImpl.*(..))")
public void pc(){}
//前置通知,目标方法运行之前调用
@Before("MyAdvice.pc()")
public void before(){
System.out.println("前置通知!");
}
//后置通知(如果出现异常不会调用),目标方法调用之后调用
@AfterReturning("execution(* com.gjh.service.*ServiceImpl.*(..))")
public void afterReturning(){
System.out.println("后置通知(异常不会调用)!");
}
//环绕通知,在目标方法之前之后都调用
@Around("execution(* com.gjh.service.*ServiceImpl.*(..))")
public Object around(ProceedingJoinPoint pjp){
System.out.println("环绕通知之前!");
Object obj=pjp.proceed();//调用目标方法
System.out.println("环绕通知之后!");
return obj;
}
//异常通知,如果出现异常就会调用
@AfterThroewing("execution(* com.gjh.service.*ServiceImpl.*(..))")
public void afterException(){
System.out.println("出现异常!");
}
//后置通知(无论是否出现异常都会调用),在目标方法运行之后调用
@After("execution(* com.gjh.service.*ServiceImpl.*(..))")
public void after(){
System.out.println("后置通知(出现一场也会调用)!");
}
}
- 配置进行织入,将通知织入目标对象中
<!-- 准备工作:导入aop(约束)命名空间 -->
<!-- 配置目标对象 -->
<bean name="userService" class="com.gjh.service.UserServiceImpl" />
<!-- 配置通知对象 -->
<bean name="advice" class="com.gjh.aop.Advice" />
<!-- 开始使用注解完成织入 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>