spring aop

aop的专业术语

Target(目标类):需要被代理的类
joinpoint(连接点):是指那些可能会被拦截的方法。
poinCut(切入点):已经被增强的连接点。
advice(通知/增强):增强的代码
weaving(织入):把增强advice应用到目标对象,创建新的代理对象的过程。
proxy:代理类
aspect(切面):切入点和通知的接口

使用jdk动态代理实现

public interface UserService {
    
    public void addUser();
    public void updateUser();
    public void deleteUser();

}
public class UserServiceImpl implements UserService {

    @Override
    public void addUser() {
        System.out.println("a_proxy.a_jdk addUser");
    }

    @Override
    public void updateUser() {
        System.out.println("a_proxy.a_jdk updateUser");

    }

    @Override
    public void deleteUser() {

        System.out.println("a_proxy.a_jdk deleteUser");
    }

}

public class MyAspect {
    
    public void before(){
        System.out.println("前置");
    }
    
    public void after(){
        System.out.println("后置");
    }

}
public class MyBeanFactory {
    
    public static UserService createService(){
        //1 目标类
        final UserService userService = new UserServiceImpl();
        //2切面类
        final MyAspect myAspect = new MyAspect();
        /* 3 代理类:将目标类(切入点)和 切面类(通知) 结合 --> 切面
         *  Proxy.newProxyInstance
         *      参数1:loader ,类加载器,动态代理类 运行时创建,任何类都需要类加载器将其加载到内存。
         *          一般情况:当前类.class.getClassLoader();
         *                  目标类实例.getClass().get...
         *      参数2:Class[] interfaces 代理类需要实现的所有接口
         *          方式1:目标类实例.getClass().getInterfaces()  ;注意:只能获得自己接口,不能获得父元素接口
         *          方式2:new Class[]{UserService.class}   
         *          例如:jdbc 驱动  --> DriverManager  获得接口 Connection
         *      参数3:InvocationHandler  处理类,接口,必须进行实现类,一般采用匿名内部
         *          提供 invoke 方法,代理类的每一个方法执行时,都将调用一次invoke
         *              参数31:Object proxy :代理对象
         *              参数32:Method method : 代理对象当前执行的方法的描述对象(反射)
         *                  执行方法名:method.getName()
         *                  执行方法:method.invoke(对象,实际参数)
         *              参数33:Object[] args :方法实际参数
         * 
         */
        UserService proxService = (UserService)Proxy.newProxyInstance(
                                MyBeanFactory.class.getClassLoader(), 
                                userService.getClass().getInterfaces(), 
                                new InvocationHandler() {
                                    
                                    @Override
                                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                        
                                        //前执行
                                        myAspect.before();
                                        
                                        //执行目标类的方法
                                        Object obj = method.invoke(userService, args);
                                        
                                        //后执行
                                        myAspect.after();
                                        
                                        return obj;
                                    }
                                });
        
        return proxService;
    }

}


public class TestJDK {
    
    @Test
    public void demo01(){
        UserService userService = MyBeanFactory.createService();
        userService.addUser();
        userService.updateUser();
        userService.deleteUser();
    }

}

cglib实现

public class UserServiceImpl {

    public void addUser() {
        System.out.println("a_proxy.b_cglib addUser");
    }

    public void updateUser() {
        System.out.println("a_proxy.b_cglib updateUser");

    }

    public void deleteUser() {

        System.out.println("a_proxy.b_cglib deleteUser");
    }

}
public class MyAspect {
    
    public void before(){
        System.out.println("鸡首2");
    }
    
    public void after(){
        System.out.println("牛后2");
    }

}

public class MyBeanFactory {
    
    public static UserServiceImpl createService(){
        //1 目标类
        final UserServiceImpl userService = new UserServiceImpl();
        //2切面类
        final MyAspect myAspect = new MyAspect();
        // 3.代理类 ,采用cglib,底层创建目标类的子类
        //3.1 核心类
        Enhancer enhancer = new Enhancer();
        //3.2 确定父类
        enhancer.setSuperclass(userService.getClass());
        /* 3.3 设置回调函数 , MethodInterceptor接口 等效 jdk InvocationHandler接口
         *  intercept() 等效 jdk  invoke()
         *      参数1、参数2、参数3:以invoke一样
         *      参数4:methodProxy 方法的代理
         *      
         * 
         */
        enhancer.setCallback(new MethodInterceptor(){

            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                
                //前
                myAspect.before();
                
                //执行目标类的方法
                Object obj = method.invoke(userService, args);
                // * 执行代理类的父类 ,执行目标类 (目标类和代理类 父子关系)
                methodProxy.invokeSuper(proxy, args);
                
                //后
                myAspect.after();
                
                return obj;
            }
        });
        //3.4 创建代理
        UserServiceImpl proxService = (UserServiceImpl) enhancer.create();
        
        return proxService;
    }

}


public class TestCglib {
    
    @Test
    public void demo01(){
        UserServiceImpl userService = MyBeanFactory.createService();
        userService.addUser();
        userService.updateUser();
        userService.deleteUser();
    }

}

spring工厂bean代理--半自动

让spring创建代理对象,然后从spring容器中手动的获取代理对象。

public interface UserService {
    
    public void addUser();
    public void updateUser();
    public void deleteUser();

}
public class UserServiceImpl implements UserService {

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

    @Override
    public void updateUser() {
        System.out.println("b_factory_bean updateUser");

    }

    @Override
    public void deleteUser() {

        System.out.println("b_factory_bean deleteUser");
    }

}
/**
 * 切面类中确定通知,需要实现不同接口,接口就是规范,从而就确定方法名称。
 * * 采用“环绕通知” MethodInterceptor
 *
 */
public class MyAspect implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        
        System.out.println("前3");
        
        //手动执行目标方法
        Object obj = mi.proceed();
        
        System.out.println("后3");
        return obj;
    }
}

xml配置



    
    
    
    

    
    
        
        
        
    

public class TestFactoryBean {
    
    @Test
    public void demo01(){
        String xmlPath = "com/itheima/b_factory_bean/beans.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
        
        //获得代理类
        UserService userService = (UserService) applicationContext.getBean("proxyServiceId");
        userService.addUser();
        userService.updateUser();
        userService.deleteUser();
    }

}

spring aop编程

上面实现了aop的半自动编程,用ProxyFactoryBean让spring来生成代理类。
但是在发现还是需要手动的获取代理类。
进一步进化。
spring利用 implements BeanPostProcessor,在类初始化的时候创建它的代理对象并返回,这样spring容器中存的实际上不是这个类,而是它的代理类,从而实现了aop。

public interface UserService {
    
    public void addUser();
    public void updateUser();
    public void deleteUser();

}

public class UserServiceImpl implements UserService {

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

    @Override
    public void updateUser() {
        System.out.println("c_spring_aop updateUser");

    }

    @Override
    public void deleteUser() {

        System.out.println("c_spring_aop deleteUser");
    }

}
/**
 * 切面类中确定通知,需要实现不同接口,接口就是规范,从而就确定方法名称。
 * * 采用“环绕通知” MethodInterceptor
 *
 */
public class MyAspect implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        
        System.out.println("前4");
        
        //手动执行目标方法
        Object obj = mi.proceed();
        
        System.out.println("后4");
        return obj;
    }
}



    
    
    
    
    
    
        
        
    

public class TestSpringAOP {
    
    @Test
    public void demo01(){
        String xmlPath = "com/itheima/c_spring_aop/beans.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
        
        //获得目标类
        UserService userService = (UserService) applicationContext.getBean("userServiceId");
        userService.addUser();
        userService.updateUser();
        userService.deleteUser();
    }

}

最终版

/**
 * 切面类,含有多个通知
 */
public class MyAspect {
    
    public void myBefore(JoinPoint joinPoint){
        System.out.println("前置通知 : " + joinPoint.getSignature().getName());
    }
    
    public void myAfterReturning(JoinPoint joinPoint,Object ret){
        System.out.println("后置通知 : " + joinPoint.getSignature().getName() + " , -->" + ret);
    }
    
    public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("前");
        //手动执行目标方法
        Object obj = joinPoint.proceed();
        
        System.out.println("后");
        return obj;
    }
    
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("抛出异常通知 : " + e.getMessage());
    }
    
    public void myAfter(JoinPoint joinPoint){
        System.out.println("最终通知");
    }

}



    
    
    
    
    
    
        
            
            
            
            
            
            
            
            
                       
            
            
            
            
        
    

注解版



    
    
    
    
    
    


/**
 * 切面类,含有多个通知
 */
@Component
@Aspect
public class MyAspect {
    
    //切入点当前有效
//  @Before("execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))")
    public void myBefore(JoinPoint joinPoint){
        System.out.println("前置通知 : " + joinPoint.getSignature().getName());
    }
    
    //声明公共切入点
    @Pointcut("execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))")
    private void myPointCut(){
    }
    
//  @AfterReturning(value="myPointCut()" ,returning="ret")
    public void myAfterReturning(JoinPoint joinPoint,Object ret){
        System.out.println("后置通知 : " + joinPoint.getSignature().getName() + " , -->" + ret);
    }
    
//  @Around(value = "myPointCut()")
    public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("前");
        //手动执行目标方法
        Object obj = joinPoint.proceed();
        
        System.out.println("后");
        return obj;
    }
    
//  @AfterThrowing(value="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))" ,throwing="e")
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("抛出异常通知 : " + e.getMessage());
    }
    
    @After("myPointCut()")
    public void myAfter(JoinPoint joinPoint){
        System.out.println("最终通知");
    }

}

你可能感兴趣的:(spring aop)