栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

关于IOC和AOP的学习

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

关于IOC和AOP的学习

IOC IOC为控制反转,是一种设计思想。DI为依赖注入,是一种实现IOC的方法。 为什么要有用IOC?

现在我们有一个接口

public interface Person {
    void talk();
}

有两个实现类

public class Man implements Person{
    @Override
    public void talk() {
        System.out.printf("我是男");
    }
}
public class Woman implements Person {
    @Override
    public void talk() {
        System.out.println("我是女");
    }
}

如果我们这样调用这里面的方法

public class PersonTalk {
    Person man = new Man();
    Person woman = new Woman();

    void manTalk() {
        man.talk();
    }

    void womenTalk() {
        woman.talk();
    }

    public static void main(String[] args) {
        PersonTalk personTalk = new PersonTalk();
        personTalk.manTalk();
        personTalk.womenTalk();
    }
}

发现假如我们要加一个实现类或者替换一个实现类会有非常多的代码量。这样耦合性会非常发高。而如果我们这样调用方法

public class PersonTalk {
    Person person;

    public void setPerson(Person person) {
        this.person = person;
    }
    void talk(){
        person.talk();
    }
    public static void main(String[] args) {
        PersonTalk personTalk = new PersonTalk();
        personTalk.setPerson(new Man());
        personTalk.talk();
        personTalk.setPerson(new Woman());
        personTalk.talk();
    }
}

我们会发现再添加一个实现类或者替换一个实现类的时候工作量会少很多,即将创建对象的主动权交给调用者而不是完全依赖于硬编码,说人话就是不再服务中直接new对象,而是在调用是自己选择。这就是IOC的原型。

(这个图片来狂神)

实现IOC的方式 Spring 实现IOC

由Spring Bean是实现IOC

什么是Spring Bean?

会Spring自动被实例化,组装及被Spring容器管理的对象。Bean和Spring容器自核在一起称为装配。就是DI的本质。

Spring 怎么自动装配(怎么做,源码以后再看吧)? 一般有两种方案
  1. 隐式的Bean发现机制和自动装配
  2. 显式配置
1.自动装配

使用 @ComponentScan扫描带带有 @Component注解的类或者在XML中使用 配置扫描。

2.显式配置

通过使用 @Bean注解或在XML中使用 指定装配的Bean

配置完之后使用 @Autowired和 @Qualifier配合使用

@Autowired就是我们在使用时的装配要使用的类

IOC是Spring的核心内容,Spring容器在初始化是先读取配置文件,根据配置文件或元数据创建于组织对象存入容器,需要是在从IOC容器中去除对象。

AOP AOP为面向切面编程,是OOP的延续.AOP主要就是在连接点执行方法. Spring实现AOP的方式 SpringAPI实现

导入依赖


    org.aspectj
    aspectjweaver
    ${aspectj.version}

public class Log implements MethodBeforeAdvice {
 
    //method : 要执行的目标对象的方法
    //objects : 被调用的方法的参数
    //Object : 目标对象
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println( o.getClass().getName() + "的" + method.getName() + "方法被执行了");
    }
}

在配置文件中注册实现



 
    
    
    
    
    
        
        
        
        
    

Spring注解实现

添加 @Aspect注解后配置切入点

@Aspect
@Component
public class WebLogAspect {
    
    private final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
    
    @Pointcut("execution(public * com.stuPayment.MainController..*.*(..))")//切入点描述 
    public void MainControllerLog(){}//签名,可以理解成这个切入点的一个名称
    
    @Pointcut("execution(public * com.UserController..*.*(..))")//切入点描述,这个是uiController包的切入点
    public void UserControllerLog(){}
    
    @Before("MainControllerLog() || UserControllerLog()") //在切入点的方法run之前要干的
    public void logBeforeController(JoinPoint joinPoint) {
        
        
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();//这个RequestContextHolder是Springmvc提供来获得请求的东西
        HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
        
         // 记录下请求内容
        logger.info("################URL : " + request.getRequestURL().toString());
        logger.info("################HTTP_METHOD : " + request.getMethod());
        logger.info("################IP : " + request.getRemoteAddr());
        logger.info("################THE ARGS OF THE ConTROLLER : " + Arrays.toString(joinPoint.getArgs()));
        
        //下面这个getSignature().getDeclaringTypeName()是获取包+类名的   然后后面的joinPoint.getSignature.getName()获取了方法名
        logger.info("################CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        //logger.info("################TARGET: " + joinPoint.getTarget());//返回的是需要加强的目标类的对象
        //logger.info("################THIS: " + joinPoint.getThis());//返回的是经过加强后的代理类的对象

    }
   
}

其中注解有:

  • @Aspect 定义切面:切面由切点和增强(引介)组成(可以包含多个切点和多个增强),它既包括了横切逻辑的定义,也包括了连接点的定义,SpringAOP就是负责实施切面的框架,它将切面所定义的横切逻辑织入到切面所指定的链接点中。
  • @Pointcut 定义切点:切点是一组连接点的集合。AOP通过“切点”定位特定的连接点。通过数据库查询的概念来理解切点和连接点的关系再适合不过了:连接点相当于数据库中的记录,而切点相当于查询条件。
  • @Before :在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可。
  • @AfterReturning : 在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值。
  • @Afterthrowing: 主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名来访问目标方法中所抛出的异常对象。
  • @After: 在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式。
  • @Around: 环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个 ProceedingJoinPoint。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/389790.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号