Spring学习03


代理设计模式

静态代理

为每一个目标类手动编写一个代理类
问题:类文件太多,额外功能难维护

动态代理

在这里插入图片描述

动态字节码框架:ASM、CGlib
增强(额外功能):

  • MethodInterceptor:事务、异常捕获
  • MethodBeforeAdvice

切入点:切入点表达式

execution(修饰符 返回值 包.类.方法(参数))

在这里插入图片描述

切入点函数

  • args(String, String)execution(* *(String, String))
  • within(*..Class)execution(* *..Class.*(..))
  • within(xx.xx..*)execution(* xx.xx..*(..))
  • @annotation(注解全类名)

切入点函数的逻辑运算

  • and:不能是同种类型的切入点函数
  • or

AOP编程

AOP(Aspect Oriented Programing)面向切面编程(动态代理开发)
AOP是对OOP的增强补充

OOP:面向对象
POP:面向过程

切面 = 切点 + 增强

JDK动态代理

动态代理类没有字节码

public class TestJDKProxy {
    public static void main(String[] args) {
        UserService userService= new UserServiceImpl();

        UserService proxy = (UserService) Proxy.newProxyInstance(UserServiceImpl.class.getClassLoader(), UserServiceImpl.class.getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("----proxy------");
                return method.invoke(userService,args);
            }
        });

        proxy.login("","");
    }
}

Cglib

针对没有实现任何借口的类(通过继承)

public class TestCglib {
    public static void main(String[] args) {
        UserService userService = new UserService();
        Enhancer enhancer =new Enhancer();
        enhancer.setClassLoader(userService.getClass().getClassLoader());
        enhancer.setSuperclass(userService.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("------cglib-----");
                return method.invoke(userService,objects);
            }
        });
        UserService proxy = (UserService) enhancer.create();
        proxy.hello();
    }
}
两种动态代理的切换
  • JDK动态代理:通过接口
  • Cglib动态代理:通过继承

默认使用JDK动态代理

<aop:config proxy-target-class="true">
<aop:aspectj-autoproxy proxy-target-class="true"/>
  • true:使用Cglib
  • false:JDK动态代理(默认)

Spring处理原始对象

通过BeanPostProcessor

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return Proxy.newProxyInstance(getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("my before enhance");
                return method.invoke(bean, args);
            }
        });
    }
}
<bean class="com.tonkia.aop.UserServiceImpl"/>
<bean class="com.tonkia.aop.MyBeanPostProcessor"/>

基于注解的AOP

@Aspect
public class AspectJTest {
    @Around("execution(* *(..))")
    public Object enhance(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("-----aspectj-------");
        Object ret = joinPoint.proceed();
        return ret;
    }
}

<bean class="com.tonkia.aop.UserServiceImpl"/>
<bean class="com.tonkia.aop.AspectJTest"/>
<aop:aspectj-autoproxy/>
PointCut注解
@Aspect
public class AspectJTest {

    @Pointcut("execution(* *(..))")
    public void myPointcut(){

    }
    @Around("myPointcut()")
    public Object enhance(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("-----aspectj-------");
        Object ret = joinPoint.proceed();
        return ret;
    }
}

ApplicationContextAware

在同一个业务类内互相调用方法,调用的是原始类的方法(而不是代理类的),如果想调用代理类的方法,需要实现ApplicationContextAware,获取ApplicationContext

public class UserServiceImpl implements UserService, ApplicationContextAware {
    ApplicationContext applicationContext;

    @Override
    public void hello() {
        System.out.println("hello");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值