Spring框架学习,day03

aop示例:demo1

package com.jt.demo1.service;

public interface UserService {
    void addUser();
}
package com.jt.demo1.service;

import org.springframework.stereotype.Service;
@Service
public class UserServiceIml implements UserService{
    /**
     * 业务:要求尽可能松耦合
     * 分析: 1.UserService是业务处理类,其中addUser方法完成用户新增
     *      2.其中事务的代码与业务代码紧紧的耦合在一起
     *      3.如果事务的机制发生了变化,则所有的代码都将改变,耦合性高
     *      当前业务的耦合性太高了!!!
     *      4.代码复用性差
     */
    @Override
    public void addUser() {
        System.out.println("事物开始");
        System.out.println("新增用户陈宫!!!");
        System.out.println("陈宫很开心!!!");
    }
}
package com.jt.demo1.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.jt.demo1")
public class SpringConfig {
}
package com.jt.demo1.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//当前类是工具API,目的是获取代理对象
public class JDKProxy {
    /**参数说明:
     * ClassLoader loader       类加载器,将class加载到java运行机制中
     * Class<?>[] interfaces    被代理者的接口数组,java可以多实现
     * InvocationHandler h      将代理对象扩展的内容写到处理器中
     * 注意事项: JDK代理必须要求 "被代理者"要么有接口(本身就是接口),要么实现接口(实现类)
     * @param target
     * @return
     */
    public static Object getProxy(Object target){
        //1.获取目标对象的类加载器
        ClassLoader loader = target.getClass().getClassLoader();
        //2.获取接口数组
        Class<?>[] interfaces = target.getClass().getInterfaces();
        //3.获取处理器对象
        InvocationHandler handler = getInvocationHandler(target);
        //4.利用动态代理获取对象
        return Proxy.newProxyInstance(loader,interfaces,handler);
    }
    public static InvocationHandler getInvocationHandler(Object target){
        //当代理对象执行业务操作时,通过InvocationHandler进行业务的扩展
        return new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("事务开始");
                //调用 让目标方法执行 target:目标对象!!! 其他都是固定写法!
                Object result = method.invoke(target, args);
                System.out.println("事务提交");
                return result;
            }
        };
    }
}
package com.jt.demo1.proxy;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxy {
    public static Object getObject(Object target){
        //创建增强器对象
        Enhancer enhancer = new Enhancer();
        //设置父级
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(getMethodInterceptor());
        return enhancer.create();
    }
    public static MethodInterceptor getMethodInterceptor(){
        return new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("数据库事务开始");
                Object proxy = methodProxy.invokeSuper(o,objects);
                System.out.println("数据库事务提交");
                return proxy;
            }
        };
    }
}
package com.jt.demo1.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TimeProxy {
    public static Object getProxy(Object target){
        ClassLoader loader = target.getClass().getClassLoader();
        Class<?>[] interfaces = target.getClass().getInterfaces();
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                long staTime = System.currentTimeMillis();
                Object result = method.invoke(target, args);
                long endTime = System.currentTimeMillis();
                System.out.println((endTime-staTime)+"毫秒");
                return result;
            }
        };
        return Proxy.newProxyInstance(loader, interfaces, handler);
    }
}
package com.jt.demo1;

import com.jt.demo1.config.SpringConfig;
import com.jt.demo1.proxy.CglibProxy;
import com.jt.demo1.proxy.JDKProxy;
import com.jt.demo1.proxy.TimeProxy;
import com.jt.demo1.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestTx {
    public static void main(String[] args) {
        ApplicationContext context =
                new AnnotationConfigApplicationContext(SpringConfig.class);
        //1.获取目标对象   userServiceIml实现类的对象
        UserService target = context.getBean(UserService.class);
        //2.获取代理对象   因为代理对象和被代理对象实现了同一个接口,因此可以进行类型的强制转换
        //JDK动态代理测试
//        UserService proxy = (UserService)JDKProxy.getProxy(target);
        //JDK动态代理测试计时
//        UserService proxy = (UserService) TimeProxy.getProxy(target);
        //Cglib动态代理测试
        UserService proxy = (UserService)CglibProxy.getObject(target);
        proxy.addUser();
    }
}

AOP示例:demo2

package com.jt.demo2.service;

public interface UserService {
    void addUser();
    String findName();
}
package com.jt.demo2.service;

import com.jt.demo2.anno.TX;
import org.springframework.stereotype.Service;
@Service
public class UserServiceIml implements UserService {
    /**
     * 业务:要求尽可能松耦合
     * 分析: 1.UserService是业务处理类,其中addUser方法完成用户新增
     *      2.其中事务的代码与业务代码紧紧的耦合在一起
     *      3.如果事务的机制发生了变化,则所有的代码都将改变,耦合性高
     *      当前业务的耦合性太高了!!!
     *      4.代码复用性差
     */
    //注解标识方式
    @TX //满足表达式,扩展方法得到展现,不满足表达式,扩展方法无法显示
    @Override
    public void addUser() {
        System.out.println("新增用户陈宫!!!");
        System.out.println("陈宫很开心!!!");
//        int a = 1/0;
    }

    @Override
    @TX
    public String findName() {
        System.out.println("中秋快乐");
//        int a = 1/0;
        return "春节愉快";
    }

}
package com.jt.demo2.service;

import com.jt.demo2.anno.TX;
import org.springframework.stereotype.Component;

@Component //key:userCommon
public class UserCommon {
    @TX
    public void say(){
        System.out.println("测试代理机制");
    }
}
package com.jt.demo2.anno;
//本类为自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD) //注解对方法有效
@Retention(RetentionPolicy.RUNTIME) //运行期有效
public @interface TX {

}
package com.jt.demo2.aop;
//本类用于测试通知方法
//AOP 面向切面编程   1年开发
//知识铺垫: 切面 = 动态代理 + 方法的扩展   后期被AOP API封装
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;

@Component  //将这个类交给spring容器管理
@Aspect     //标识当前类是一个切面
@Order(value = 1) //数字越小,越先执行
public class TxAspect {
    //编码: 切面 = 切入点表达式 + 通知方法
    //切入点表达式:为谁创建代理对象!!!
//    @Pointcut("bean(userServiceIml)") //标识切入点表达式  识别一个类
//    @Pointcut("within(com.jt.demo2..service.*)") //识别多个类
//    @Pointcut("execution(void com.jt.demo2.service.UserServiceIml.addUser())")
    @Pointcut("@annotation(com.jt.demo2.anno.TX)")
    public void pointCut(){
    }
    //通知方法:对原有方法的扩展
    //1.前置通知:在目标方法运行前,执行本方法
    @Before("pointCut()") //通知注解
    public void before(JoinPoint joinPoint){
        //1.获取目标对象的类型
        Class targetClass = joinPoint.getTarget().getClass();
        //2.获取目标对象的名称
        String targetName = joinPoint.getSignature().getDeclaringTypeName();
        //3.获取目标方法的名称
        String methodName = joinPoint.getSignature().getName();
        //4.获取目标方法的参数
        Object[] args = joinPoint.getArgs();
        System.out.println("目标对象类型:"+targetClass);
        System.out.println("目标对象名称:"+targetName);
        System.out.println("目标方法名称:"+methodName);
        System.out.println("目标方法参数:"+ Arrays.toString(args));
    }
    //2.后置通知:目标方法正常运行后,执行本方法
    /**记录目标方法的返回值结果
     *  returning: 后置通知获取返回值的属性*/
    @AfterReturning(value = "pointCut()",returning = "result")
    public void afterReturning(Object result){
        System.out.println("方法的返回值:"+result);
    }
    //3.抛出异常通知:如果目标方法运行时抛出异常,执行本方法
    /**说明:如果程序执行抛出异常,则可以由异常通知进行记录
     *      throwing:抛出异常的属性
     */
    @AfterThrowing(value = "pointCut()",throwing = "exception")
    public void afterThrowing(Exception exception){
        //exception.printStackTrace();
        System.out.println("异常信息:"+exception.getMessage());
    }
    //4.最终通知:不管目标方法是否正常执行,都会执行本方法
    @After("pointCut()")
    public void after(){
        System.out.println("我是最后通牒");
    }
    /*5.环绕通知:
    * 说明:1.前四大通知类型不能控制目标方法的运行,所以使用时一般记录程序的运行状态
    *     2.在目标方法执行前后都要运行,只有环绕通知才可以控制目标方法是否运行,使用最多的通知方法
    * 注意事项:环绕通知中必须添加参数,且参数必须位于第一位
    * 用法:
    * Proceed with the next advice or target method invocation
    * 1.如果有下一个通知,则执行下一个通知
    * 2.如果没有下一个通知,则执行目标方法*/
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知开始");
        Object result = joinPoint.proceed();
        System.out.println("环绕通知结束");
        return result;
    }
}
package com.jt.demo2.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Order(value = 2)
public class Aspect2 {
    @Around("@annotation(com.jt.demo2.anno.TX)")
    public Object around(ProceedingJoinPoint joinPoint)throws Throwable{
        System.out.println("环绕通知开始2");
        Object result = joinPoint.proceed();
        System.out.println("环绕通知结束2");
        return result;
    }
}
package com.jt.demo2.config;
//本类为配置类
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan("com.jt.demo2")
@EnableAspectJAutoProxy
//强制使用Cglib动态代理
//@EnableAspectJAutoProxy(proxyTargetClass = true)
public class SpringConfig {
}
package com.jt.demo2;

import com.jt.demo2.config.SpringConfig;
import com.jt.demo2.service.UserCommon;
import com.jt.demo2.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TsetTx {
    public static void main(String[] args) {
        ApplicationContext context =
                new AnnotationConfigApplicationContext(SpringConfig.class);
        //看上去:是目标对象     AOP:内部已经封装动态代理规则
        //实际上:已经被AOP封装,是一个代理对象
        UserService user = context.getBean(UserService.class);
        System.out.println(user.getClass());
        //代理机制,可以扩展方法
//        user.addUser();
        user.findName();

        //测试cglib代理模式
        UserCommon userCommon = context.getBean(UserCommon.class);
        System.out.println(userCommon.getClass());
        userCommon.say();
    }
}

AOP示例:demo3

package com.jt.demo3.service;

public interface UserService {
    void addUser();
}
package com.jt.demo3.service;

import org.springframework.stereotype.Service;
@Service
public class UserServiceIml implements UserService {
    @Override
    public void addUser() {
        System.out.println("三英战吕布!!!");
        int a = 1/0;
    }
}
package com.jt.demo3.aop;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.util.logging.SocketHandler;

@Component
@Aspect //标识当前类是切面类
public class DemoAspect {
    //作用:如果匹配了切入点表达式,为其创建代理对象 jdk动态代理
    @Around("bean(userServiceIml)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long end = System.currentTimeMillis();
        System.out.println("耗时:"+(end-start));

        //获取数据信息
        Class<?> targetClass = joinPoint.getTarget().getClass();
        String typeName = joinPoint.getSignature().getDeclaringTypeName();
        String name = joinPoint.getSignature().getName();
        System.out.println("目标对象的类型:"+targetClass);
        System.out.println("目标对象的名称:"+typeName);
        System.out.println("目标方法的名称:"+name);
        return result;
    }

    /*@AfterThrowing("execution(返回值类型 包名.类名.方法名(参数列表))")
    * ps:1.'*'号表示所有类型
    *    2.'..'表示不做限制*/
    @AfterThrowing("execution(* com.jt.demo3.service..*.*(..))")
    public void afterThrowing(){
        System.out.println("关羽窜稀了!!!");
    }
}
package com.jt.demo3.config;
//本类为配置类
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan("com.jt.demo3")
@EnableAspectJAutoProxy
public class SpringConfig {
}
package com.jt.demo3;

import com.jt.demo3.config.SpringConfig;
import com.jt.demo3.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestDemo {
    public static void main(String[] args) {
        ApplicationContext context =
                new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService user = context.getBean(UserService.class);
        user.addUser();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring框架是一个非常流行的Java开发框架,它提供了一种轻量级的、面向对象的编程模型,用于构建企业级应用程序。学习Spring框架可以帮助你更加高效地开发Java应用程序,并且提供了很多功能和特性来简化开发过程。 如果你想学习Spring框架,我建议你按照以下步骤进行: 1. 基本概念:首先,了解Spring框架的基本概念和核心特性,例如控制反转(IoC)和面向切面编程(AOP)。可以阅读官方文档或者参考一些教程来获得更多的了解。 2. Spring Boot:学习使用Spring Boot,它是Spring框架的一个扩展,可以更加简化和加速应用程序的开发过程。掌握Spring Boot可以帮助你更好地配置和管理Spring应用程序。 3. 数据访问:学习使用Spring框架的数据访问功能,例如使用Spring JDBC或者Spring Data JPA来连接数据库,并执行CRUD操作。 4. Web开发:掌握使用Spring框架进行Web开发的技术,例如使用Spring MVC来构建Web应用程序,并了解RESTful API的设计和实现。 5. 安全性:学习使用Spring Security来保护你的应用程序,包括认证和授权等方面的功能。 6. 测试:了解如何使用Spring框架进行单元测试和集成测试,确保你的应用程序的质量和稳定性。 除了上述步骤,还可以参与一些实际项目或者练习来巩固所学的知识。同时,阅读Spring框架的源代码也是一个很好的学习方式,可以加深对框架内部实现原理的理解。 希望这些步骤能够帮助你开始学习Spring框架!如果你还有其他问题,可以继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值