Spring的两大核心(SpringIOC、SpringAOP)

一:SpringIOC

        IOC(中文释义:控制反转),主要作用于解耦。IOC是指将创建对象的控制权交给spring框架进行管理,spring框架根据配置文件或注解等方式,创建bean对象并管理各个bean对象之家的依赖关系,使对象之间形成耦合松散的状态,实现解耦。

        控制:指的是对象创建(实例化、管理)的权力

        反转:控制权交给外部环境(spring框架、IOC容器)

IOC的使用

(1)导入坐标

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.27</version>
</dependency>

(2)将需要已解耦创建的对象,类注入springIOC容器

<bean id="类的唯一标识" class="注入的类"></bean>

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="StudentDaoImpl" class="com.apesource.dao.StudentDaoImpl"></bean>

    <bean id="StudentserviceImpl" class="com.apesource.service.StudentserviceImpl"/>

    <bean id="Date" class="java.util.Date"> </bean>

</beans>

(3)向springIOC容器索取实例

package com.apesource.test;

import com.apesource.dao.IStudentDao;
import com.apesource.service.IStudentservice;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Date;

public class Test {
    public static void main(String[] args){
        ApplicationContext context =new ClassPathXmlApplicationContext("beans.xml");
        IStudentDao dao=(IStudentDao) context.getBean("StudentDaoImpl");

        IStudentservice service =(IStudentservice) context.getBean("StudentserviceImpl");
        Date date=(Date) context.getBean("Date");
        System.out.println(date);
        service.save();
        dao.save();
    }
}

二:SpringDI(依赖注入)

        DI(依赖注入) 是对IOC概念的不同角度的描述,是指应用程序在运行时,每一个bean对象都依赖IOC容器注入当前bean对象所需要的另外一个bean对象。

1.DI的使用

(1)提供set方法(或者构造方法)

package com.apesource.Controller;

import com.apesource.service.StudentServiceImpl;

public class StudentControllerImpl implements IStudentController{
    StudentServiceImpl service;

    public void setService(StudentServiceImpl service) {
        this.service = service;
    }

    @Override
    public void save() {
        System.out.println("controller的新增");
        service.save();
    }
}

(2)配置标签

语法:<property name="属性名" ref="关联的id"></property>

位置:<bean>此位置</bean>

<bean id="StudentControllerImpl" class="com.apesource.Controller.StudentControllerImpl">
    <property name="service" ref="StudentServiceImpl"></property>
 </bean>

2.DI注入方式

        A.set注入

        B.构造注入

构造注入即为将set方法改为构造方法即可。

3.DI注入数据类型

        A.基本类型与String

        B.javaBean对象

        C.复杂类型

复杂类型包括:list、set、String[]、map、properties

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="StudentControllerImpl" class="com.apesource.Controller.StudentControllerImpl">
        <property name="service" ref="StudentServiceImpl"></property>
     </bean>

    <bean id="student" class="com.apesource.bean.Student">
        <property name="name" value="蜡笔小新"></property>
        <property name="age" value="10"></property>
        <property name="hobby" value="玩玩具"></property>
    </bean>

    <bean id="teacher" class="com.apesource.bean.Teacher">
        <property name="list">
            <list>
                <value>哪吒2</value>
                <value>唐探</value>
                <value>熊出没重启未来</value>
                <value>封神2</value>
                <value>射雕英雄传</value>
            </list>
        </property>
        <property name="set">
            <set>
                <value>西安</value>
                <value>宝鸡</value>
                <value>郑州</value>
                <value>兴平</value>
                <value>延安</value>
            </set>
        </property>
    </bean>

</beans>

三SpringAOP

AOP(Aspect-Oriented Programming: 面向切面编程):将那些与业务无关,却为业务模块所共同调用的逻辑(例如事务处理、日志管理、权限控制等)封装抽取成一个可重用的模块,这个模块被命名为“切面”(Aspect),便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性;

Spring AOP 基于动态代理实现:

○ 如果被代理的对象,已经实现某个接口,则 Spring AOP 会使用 JDK Proxy(反射),基于接口的方式,创建代理对象(JDK动态代理的核心是InvocationHandler接口和Proxy类);

○ 如果被代理的对象,没有实现某个接口,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib,基于继承的方式,生成一个被代理对象的子类来作为代理(Cglib动态代理的核心是MethodInterceptor接口和Enhancer类);

(1)AOP的通知类型

AOP将抽取出来的共性功能称为通知;通知类型:以通知在上下文中的具体位置作为划分

        前置通知(Before)

        后置通知(After)

        返回通知(After-returning)

        异常通知(After-throwing)

        环绕通知(Around)

(2)AOP连接点(Join point)

AOP将所有的方法都视为连接点,不管是接口里面的抽象方法,还是实现类里面的重写方法,都是连接点。

AOP切点(Pointcut)

AOP将可能被抽取共性功能的方法称为切入点。切入点是连接点的子集

AOP目标对象(Target): 就是挖掉功能的方法对应的类生的对象,这种对象是无法直接完成最终工作的。

AOP织入(Weaving):就是将挖掉的功能回填的动态过程

(3)AOP切面:切点+通知

1.添加依赖,aop与aspectj表达式的依赖

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.7</version>
</dependency>

2.创建spring的主配置文件,bean内的命名空间要添加aop的

3.创建业务代码并编写日志记录代码(事务管理代码)

4.将业务层与日志记录层注入spring容器

5.<aop:config>--aop配置

        aop:aspect--aop切面

        aop:before--通知内容与通知类型

切点表达式配置语法:

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

eg:

execution(public void com.apesource.service.ServiceImp.findAll())

1.修饰符可以省略代表任意

        execution(返回值 包名称.类名称.方法名称(参数列表))

2.返回值可以使用“*”代表任意

        execution(* 包名称.类名称.方法名称(参数列表))

3.包名可以使用“*”代表任意名称

        execution(* *.*.*.类名称.方法名称(参数列表))

4.包名可以使用“..”代表任意个数

        execution(* *...类名称.方法名称(参数列表))

5.类名与方法名可以使用“*”代表任意

        execution(* *...*.*(参数列表))

6.参数列表可以使用".."代表任意个数任意类型

        execution(* *...*.*(..))

如果有参数

int======>int

String===>java.lang.String

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="service" class="com.apesource.service.CountServiceImpl"></bean>
    <bean id="logger" class="com.apesource.util.Logger"></bean>
    <!--配置Aop-->
    <aop:config>
        <!--配置切面-->
        <aop:aspect id="aopAspect" ref="logger">
            <!--配置切点-->
            <aop:pointcut id="pointCut" expression="execution(* com.apesource.service.*.*(..))"></aop:pointcut>
<!--            &lt;!&ndash;前置通知&ndash;&gt;-->
<!--            <aop:before method="beforeLogger" pointcut-ref="pointCut"></aop:before>-->
<!--            &lt;!&ndash;返回通知&ndash;&gt;-->
<!--            <aop:after-returning method="returnLogger" pointcut-ref="pointCut"></aop:after-returning>-->
<!--            &lt;!&ndash;异常通知&ndash;&gt;-->
<!--            <aop:after-throwing method="throwLogger" pointcut-ref="pointCut"></aop:after-throwing>-->
<!--            &lt;!&ndash;后置通知&ndash;&gt;-->
<!--            <aop:after method="afterLogger" pointcut-ref="pointCut"></aop:after>-->
            <aop:around method="aroundLogger" pointcut-ref="pointCut"></aop:around>
        </aop:aspect>
    </aop:config>
</beans>
package com.apesource.util;

import org.aspectj.lang.ProceedingJoinPoint;

public class Logger {
    public void beforeLogger(){
        System.out.println("日志类logger中调用前置通知进行日志记录");
    }
    public void returnLogger(){
        System.out.println("日志类logger中调用返回通知进行日志记录");
    }
    public void throwLogger(){
        System.out.println("日志类logger中调用异常通知进行日志记录");
    }
    public void afterLogger(){
        System.out.println("日志类logger中调用后置通知进行日志记录");
    }

    public Object aroundLogger(ProceedingJoinPoint pjp){
        Object obj = null;
        try {
            System.out.println("环绕通知的前置通知");
            obj =pjp.proceed(pjp.getArgs());
            System.out.println("环绕通知的返回通知");
        } catch (Throwable e) {
            e.printStackTrace();
            System.out.println("环绕通知的异常通知");
        }finally {
            System.out.println("环绕通知的后置通知");
        }
        return obj;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值