IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring5学习笔记(部分) -> 正文阅读

[Java知识库]Spring5学习笔记(部分)

目录

1、Spring概念

2、Ioc容器

1、什么是Ioc

2、底层原理

入门案例

4、Spring提供Ioc容器实现的两种方式(两个接口)

5、ApplicationContext接口的常用实现类

6、什么是Bean管理

7、Bean管理的两种方式

3、Aop

1、什么是Aop?

?2、使用JDK动态代理,使用Proxy类里面的方法创建代理对象

3、AOP一些专业术语

?4、AOP操作(准备)

?5、AOP操作(AspectJ注解方式)

??6、AOP操作(AspectJ配置文件方式)


?课程链接:尚硅谷-Spring5框架最新版教程(idea版)_哔哩哔哩_bilibili

Spring官网:Spring | Home

jar下载地址(我是找的maven仓库,哪里下载都可以):https://mvnrepository.com/


1、Spring概念

Spring是轻量级的开源的J2EE框架

Spring解决企业级应用开发的复杂性

Spring有两个核心部分:Ioc(控制反转:将创建对象的过程交给Spring来管理)、Aop(面向切面编程:在不改变源码的基础上对功能进行增强)

Spring特点:

? ? ? ? (1)、方便解耦、简化开发

? ? ? ? (2)、AOP编程的支持

? ? ? ? (3)、方便程序的测试

? ? ? ? (4)、方便和其他框架整合

? ? ? ? (5)、方便进行事务的操作

? ? ? ? (6)、降低API的开发难度

2、Ioc容器

1、什么是Ioc

(1)控制反转就是把创建对象和对象之间的调用交给Spring进行管理

(2)使用Ioc目的:为了降低耦合度

2、底层原理

? ? ? ? xml解析、工厂模式、反射

主要用到的jar包:????????

????????????????????????????????spring-beans-5.2.6.RELEASE.jar

????????????????????????????????spring-context-5.2.6.RELEASE.jar

????????????????????????????????spring-core-5.2.6.RELEASE.jar

????????????????????????????????spring-expression-5.2.6.RELEASE

????????????????????????????????commons-logging-1.2.jar(Spring不含此包,需要单独下载)

入门案例

利用配置文件创建对象、注入属性

User.java

package com.atguigu.spring5;

/**
 * 创建对象演示类
 */
public class User {
    public void add(){
        System.out.println("add.....");
    }
}

Book.java

package com.atguigu.spring5;

public class Book {
    private String bname;
    private String bauthor;

    public void setBname(String bname) {
        this.bname = bname;
    }

    public void setBauthor(String bauthor) {
        this.bauthor = bauthor;
    }public void print(){
        System.out.println(bname+bauthor);
    }
}

Orders.java

package com.atguigu.spring5;

/**
 * 利用构造方法注入属性演示类
 */
public class Orders {
    private String oname;
    private String address;
    public Orders(String oname,String address){
        this.oname=oname;
        this.address=address;

    }

    public void print() {
        System.out.println(oname+address);
    }
}

配置文件bean1.xml

<?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">

    <!-- 配置User对象创建 -->
    <bean id="user" class="com.atguigu.spring5.User"></bean>
    <bean id="book" class="com.atguigu.spring5.Book">
        <!-- 使用property完成属性注入(set方法) -->
        <property name="bname" value="易筋经"></property>
        <property name="bauthor" value="达摩"></property>
    </bean>
    <bean id="orders" class="com.atguigu.spring5.Orders">
        <!-- 使用constructor-arg完成属性注入(构造方法) -->
        <constructor-arg name="oname" value="电脑"/>
        <constructor-arg name="address" value="中国"/>
    </bean>
</beans>

测试类TestSpring5.java

package com.atguigu.spring5.testdemo;

import com.atguigu.spring5.Book;
import com.atguigu.spring5.Orders;
import com.atguigu.spring5.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSpring5 {

    @Test
    public void testAdd(){
        ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml");
        User user =context.getBean("user", User.class);
        System.out.println(user);
        user.add();
    }
    @Test
    public void testBook(){
        ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml");
        Book book=context.getBean("book",Book.class);
        System.out.println(book);
        book.print();
    }
    @Test
    public void testOrders(){
        ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml");
        Orders orders=context.getBean("orders",Orders.class);
        System.out.println(orders);
        orders.print();
    }
}

控制台打印

com.atguigu.spring5.User@a74868d
add.....
com.atguigu.spring5.Book@2eda0940
易筋经达摩
com.atguigu.spring5.Orders@4c762604
电脑中国

Process finished with exit code 0

4、Spring提供Ioc容器实现的两种方式(两个接口)

?(1)、BeanFactory*:Ioc容器基本实现,是Spring内部使用接口,一般不提供给开发人员使用。在加载配置文件的时候不会创建对象,在获取对象(使用)时才会去创建对象

?(2)、ApplicationContext:是BeanFactory的子接口,提供更多更强大的功能,一般有开发人员使用。在加载配置文件的时候就会创建配置文件中配置的对象。

*在实际项目中一般把耗时耗资源的操作在项目启动时处理所以用ApplicationContext更合适。

5、ApplicationContext接口的常用实现类

(1)FileSystemXmlApplicationContext

(2)ClassPathXmlApplicationContext

6、什么是Bean管理

主要指两个操作

(1)、Spring创建对象

(2)、Spring注入属性

7、Bean管理的两种方式

(1)、基于xml配置文件方式实现

????????使用<bean>标签创建对象

<!-- 配置User对象创建 -->
    <bean id="user" class="com.atguigu.spring5.User"></bean>

? ? ? 在创建对象的基础上使用<property>标签注入属性

    <bean id="book" class="com.atguigu.spring5.Book">
        <!-- 使用property完成属性注入(set方法) -->
        <property name="bname" value="易筋经"></property>
        <property name="bauthor" value="达摩"></property>
    </bean>

? ?向属性中设置空值

<bean id="book" class="com.atguigu.spring5.Book">
        <!-- 使用property完成属性注入(set方法) -->
        <property name="bname" value="易筋经"></property>
        <property name="bauthor">
            <!--向属性中设置空值-->
            <null/>
        </property>
    </bean>

?向属性中设置特殊符号

    <bean id="book" class="com.atguigu.spring5.Book">
        <!-- 使用property完成属性注入(set方法) -->
        <!-- 设置特殊符号 -->
        <!-- 使用转义字符输入<<>> -->
        <property name="bname" value="&lt;&lt;易筋经&gt;&gt;"></property>
        <!-- 把带有特殊符号的内容写到CDATA -->
        <property name="bauthor">
            <value><![CDATA[<<达摩>>]]></value>
        </property>
    </bean>

?????使用<constructor-arg>标签注入属性

<bean id="orders" class="com.atguigu.spring5.Orders">
    <!-- 使用constructor-arg完成属性注入(构造方法) -->
    <constructor-arg name="oname" value="电脑"/>
    <constructor-arg name="address" value="中国"/>
</bean>

使用<property>标签ref属性注入属性对象(外部注入)

<bean id="userService" class="com.atguigu.spring5.service.UserService">
    <!--注入属性对象-->
    <property name="userDao" ref="userDaoImpl"></property>
</bean>
<!--创建要注入的对象-->
<bean id="userDaoImpl" class="com.atguigu.spring5.dao.UserDaoImpl"></bean>

注入属性对象(内部注入)

<bean id="emp" class="com.atguigu.spring5.bean.Emp">
    <property name="ename" value="lucy"></property>
    <property name="gender" value="女"></property>
    <property name="dept">
        <bean id="dept" class="com.atguigu.spring5.bean.Dept">
            <property name="dname" value="保安部"></property>
        </bean>
    </property>
</bean>

级联赋值(两种写法)

<bean id="emp" class="com.atguigu.spring5.bean.Emp">
    <property name="ename" value="lucy"></property>
    <property name="gender" value="女"></property>
    <property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="com.atguigu.spring5.bean.Dept">
    <property name="dept.dname" value="保安部"></property>
</bean>
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
    <property name="ename" value="lucy"></property>
    <property name="gender" value="女"></property>
    <property name="dept" ref="dept">
    <!--注入dept的属性,属性需要有get方法-->
    <property name="dept.dname" value="保安部"></property>
    </property>
</bean>
<bean id="dept" class="com.atguigu.spring5.bean.Dept"></bean>

注入集合属性

 <bean id="stu" class="com.atguigu.spring5.collectiontype.Stu">
        <!--注入数组属性-->
        <property name="courses">
            <array>
                <value>java课程</value>
                <value>数据库课程</value>
            </array>
        </property>
        <property name="list">
            <list>
                <value>张三</value>
                <value>法外狂徒</value>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="JAVA" value="java"></entry>
                <entry key="PHP" value="php"></entry>
            </map>
        </property>
        <property name="sets">
            <set>
                <value>MySQL</value>
                <value>Redis</value>
            </set>
        </property>
        <property name="courseList">
            <!--对象类型的集合-->
            <list>
                <ref bean="course1"></ref>
                <ref bean="course2"></ref>
            </list>
        </property>
    </bean>
    <bean class="com.atguigu.spring5.collectiontype.Course" id="course1">
        <property name="cname" value="Spring5框架"></property>
    </bean>
    <bean class="com.atguigu.spring5.collectiontype.Course" id="course2">
        <property name="cname" value="MyBatis"></property>
    </bean>

引入util名称空间,把集合注入部分提取出来

<?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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util.xsd">

    <util:list id="bookList">
        <value>易筋经</value>
        <value>九阳神功</value>
        <value>大悲咒</value>
    </util:list>
    <bean class="com.atguigu.spring5.collectiontype.Book" id="book" scope="prototype">
        <property name="list" ref="bookList"></property>
    </bean>
</beans>

工厂bean(FactoryBean)

package com.atguigu.spring5.factorybean;

import com.atguigu.spring5.collectiontype.Course;
import org.springframework.beans.factory.FactoryBean;

public class MyBean implements FactoryBean<Course> {

    @Override
    public Course getObject() throws Exception {
        Course course=new Course();
        course.setCname("aaa");
        return course;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return FactoryBean.super.isSingleton();
    }
}
package com.atguigu.spring5.collectiontype;

public class Course {
    private String cname;

    public void setCname(String cname) {
        this.cname = cname;
    }

    @Override
    public String toString() {
        return "Course{" +
                "cname='" + cname + '\'' +
                '}';
    }
}
<?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 class="com.atguigu.spring5.factorybean.MyBean" id="myBean">

    </bean>
</beans>

测试工厂bean的方法

@Test
    public void test3() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
        Course course = context.getBean("myBean", Course.class);
        System.out.println(course);
    }

控制台输出结果

Course{cname='aaa'}

Process finished with exit code 0

利用bean标签scope属性设置bean是单实例对象还是多实例对象,Spring中默认是单实例对象

*(单实例每次创建都是引用同一个对象,多实例每次创建都是一个新的对象)

测试方法(多次获取对象输出,比较对象是否相同)

    @Test
    public void testCollection2() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
        Book book1 = context.getBean("book", Book.class);
        Book book2 = context.getBean("book", Book.class);
        System.out.println(book1);
        System.out.println(book2);
    }

单实例配置?

<?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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

<util:list id="bookList">
    <value>易筋经</value>
    <value>九阳神功</value>
    <value>大悲咒</value>
</util:list>
    <!--默认和scope="singleton"为单实例-->
<bean class="com.atguigu.spring5.collectiontype.Book" id="book" scope="singleton">
    <property name="list" ref="bookList"></property>
</bean>
</beans>

?输出的两次对象相同

com.atguigu.spring5.collectiontype.Book@10d59286
com.atguigu.spring5.collectiontype.Book@10d59286

Process finished with exit code 0

多实例配置?

<?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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

<util:list id="bookList">
    <value>易筋经</value>
    <value>九阳神功</value>
    <value>大悲咒</value>
</util:list>
    <!--多实例-->
<bean class="com.atguigu.spring5.collectiontype.Book" id="book" scope="prototype">
    <property name="list" ref="bookList"></property>
</bean>
</beans>

输出的两次对象不同?

com.atguigu.spring5.collectiontype.Book@10d59286
com.atguigu.spring5.collectiontype.Book@fe18270

Process finished with exit code 0

Bean生命周期演示?

package com.atguigu.spring5.bean;

public class Orders {
    private String oname;
    public Orders() {
        System.out.println("第一步:创建bean实例");
    }

    public void setOname(String oname) {
        System.out.println("第二步:调用set方法赋值");
        this.oname = oname;

    }
    public void initMethod(){
        //需要在配置文件中配置
        System.out.println("第三步:调用初始化方法");
    }

    private void destroyMethod() {
        //需要在配置文件中配置,手动调用才会执行
        System.out.println("第五步:调用销毁方法");
    }
}
<?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">
    <!--init-method配置初始化方法,destroy-method配置销毁方法-->
    <bean class="com.atguigu.spring5.bean.Orders" id="orders" init-method="initMethod" destroy-method="destroyMethod">
        <property name="oname" value="手机"></property>
    </bean>
</beans>
    @Test
    public void testBean() {
//        ApplicationContext context=new ClassPathXmlApplicationContext("bean4.xml");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
        Orders orders = context.getBean("orders", Orders.class);
        System.out.println("第四步:获取到创建出来的bean对象" + orders);
        //手动调用销毁方法
        context.close();
    }

?控制台输出

第一步:创建bean实例
第二步:调用set方法赋值
第三步:调用初始化方法
第四步:获取到创建出来的bean对象com.atguigu.spring5.bean.Orders@569cfc36
第五步:调用销毁方法

Process finished with exit code 0

?添加后置处理器后的生命周期

package com.atguigu.spring5.bean;

import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPost implements BeanPostProcessor {
    @Override
    public java.lang.Object postProcessBeforeInitialization(java.lang.Object bean, java.lang.String beanName) throws org.springframework.beans.BeansException {
        System.out.println("在初始化之前执行的方法");
        return bean;
    }

    @Override
    public java.lang.Object postProcessAfterInitialization(java.lang.Object bean, java.lang.String beanName) throws org.springframework.beans.BeansException {
        System.out.println("在初始化之后执行的方法");
        return 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 class="com.atguigu.spring5.bean.Orders" id="orders" init-method="initMethod" destroy-method="destroyMethod">
        <property name="oname" value="手机"></property>
    </bean>
    <!--配置后置处理器-->
    <bean class="com.atguigu.spring5.bean.MyBeanPost" id="myBeanPost"></bean>
</beans>
第一步:创建bean实例
第二步:调用set方法赋值
在初始化之前执行的方法
第三步:调用初始化方法
在初始化之后执行的方法
第四步:获取到创建出来的bean对象com.atguigu.spring5.bean.Orders@569cfc36
第五步:调用销毁方法

Process finished with exit code 0

?自动装配(自动为属性赋值:根据名称/根据类型)

通过设置Bean标签中autowire属性

根据属性名称自动装配

<?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 class="com.atguigu.spring5.autowire.Emp" id="emp" autowire="byName">
<!--        <property name="dept" ref="dept"></property>-->
    </bean>
    <bean class="com.atguigu.spring5.autowire.Dept" id="dept"></bean>
</beans>

根据属性类型自动装配?

<?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 class="com.atguigu.spring5.autowire.Emp" id="emp" autowire="byType">
<!--        <property name="dept" ref="dept"></property>-->
    </bean>
    <bean class="com.atguigu.spring5.autowire.Dept" id="dept"></bean>
</beans>

?引入外部文件

直接配置

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/userDb"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>
</beans>

?引入外部.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--需要引入context名称空间-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
        <property name="driverClassName" value="${prop.driverClass}"></property>
        <property name="url" value="${prop.url}"></property>
        <property name="username" value="${prop.userName}"></property>
        <property name="password" value="${prop.password}"></property>
    </bean>
</beans>

jdbc.properties?

prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/userDb
prop.userName=root
prop.password=123456

?(2)、基于注解方式实现

注解是代码特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值..)

注解可以作用在类、方法、属性上面

使用注解的目的:简化xml配置,

创建对象的注解:

  1. @Component 业务特殊组件层,如handler类
  2. @Controller 业务控制层
  3. @Service 业务逻辑层
  4. @Repository 业务资源层

*这四个注解功能是一样的,都可以用来创建Bean实例

?基于注解方式创建对象

需要先引入aop依赖:spring-aop-5.2.6.RELEASE.jar

xml配置方式开启组件扫描

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 开启组件扫描 -->
    <!-- base-package属性多个包可以用“,”隔开。相同目录下多个包,写上层目录 -->
    <context:component-scan base-package="com.atguigu.spring5"></context:component-scan>

    <!--use-default-filters="false"表示现在不使用默认的filter,自己配置filter,context:include-filter:设置扫描哪些内容-->
    <!--<context:component-scan base-package="com.atguigu.spring5" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>-->

    <!--context:exclude-filter:设置哪些内容不扫描-->
    <!--<context:component-scan base-package="com.atguigu.spring5">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>-->
</beans>

?注解方式开启组件扫描

package com.atguigu.spring5.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = {"com.atguigu"})
public class SpringConfig {

}

?自动装配类UserService

package com.atguigu.spring5.Service;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

//注解里value值可以省略,默认是首字母小写的类名,例如UserService类默认为userService
//@Component(value = "userService")
@Service
public class UserService {

    public void add(){
        System.out.println("service add..........");
    }
}

测试方法?

package com.atguigu.spring5.testdemo;

import com.atguigu.spring5.Service.UserService;
import com.atguigu.spring5.config.SpringConfig;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSpring5Demo1 {

    //基于xml配置文件开启扫描器的测试方法
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }

    //基于注解开启扫描器的测试方法
    @Test
    public void test2() {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }
}

两次输出结果相同?

com.atguigu.spring5.Service.UserService@2f7c2f4f
service add..........

Process finished with exit code 0

?基于注解方式注入属性

????????@AutoWired:根据属性类型进行注入

????????@Qualifer:根据属性名称进行注入

????????@Resource:可以根据类型注入,也可以根据名称注入(不属于Spring,属于Javax)

????????@Value:普通类型属性注入

package com.atguigu.spring5.dao;

public interface UserDao {
    public void add();
}
package com.atguigu.spring5.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao{
    @Override
    public void add(){
        System.out.println("Dao add.........");
    }
}

?根据类型注入

package com.atguigu.spring5.Service;

import com.atguigu.spring5.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

//@Component(value = "userService")
@Service
public class UserService {

    //不需要set方法
    //根据属性注入
    @Autowired
    private UserDao userDao;

    public void add(){
        System.out.println("service add..........");
        userDao.add();
    }
}
com.atguigu.spring5.Service.UserService@123ef382
service add..........
Dao add.........

Process finished with exit code 0

?根据名称注入

package com.atguigu.spring5.dao;

import org.springframework.stereotype.Repository;

@Repository(value = "userDaoImpl1")
public class UserDaoImpl implements UserDao{
    @Override
    public void add(){
        System.out.println("Dao add.........");
    }
}
package com.atguigu.spring5.Service;

import com.atguigu.spring5.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

//@Component(value = "userService")
@Service
public class UserService {
    @Autowired
    //当有多个实现类时就需要按名称注入,搭配@Autowired
    @Qualifier(value = "userDaoImpl1")
    private UserDao userDao;

    public void add(){
        System.out.println("service add..........");
        userDao.add();
    }
}

??@Resource:可以根据类型注入,也可以根据名称注入

package com.atguigu.spring5.Service;

import com.atguigu.spring5.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

//@Component(value = "userService")
@Service
public class UserService {
    
    //@Resource根据类型注入
    @Resource
    private UserDao userDao;

    public void add(){
        System.out.println("service add..........");
        userDao.add();
    }
}
package com.atguigu.spring5.Service;

import com.atguigu.spring5.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

//@Component(value = "userService")
@Service
public class UserService {

    //@Resource根据名称注入
    @Resource(name = "userDoImpl1")
    private UserDao userDao;

    public void add(){
        System.out.println("service add..........");
        userDao.add();
    }
}

?@Value普通类型注入

package com.atguigu.spring5.Service;

import com.atguigu.spring5.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

//@Component(value = "userService")
@Service
public class UserService {
    @Autowired
    //当有多个实现类时就需要按名称注入,搭配@Autowired
    @Qualifier(value = "userDaoImpl1")
//    //@Resource根据类型注入
//    @Resource
//    //@Resource根据名称注入
//    @Resource(name = "userDoImpl1")
    private UserDao userDao;

    //注入普通类型
    @Value(value = "abc")
    private String name;

    public void add(){
        System.out.println("service add.........."+name);
        userDao.add();
    }
}
com.atguigu.spring5.Service.UserService@bef2d72
service add..........abc
Dao add.........

Process finished with exit code 0

3、Aop

1、什么是Aop?

(1)、面向切面(方面)编程,利用Aop可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各个部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

(2)、通俗来说:就是不通过修改源码的方式,往主干功能里增加新功能。

(3)、底层原理:

? ? ? ? Aop底层使用动态代理

? ? ? ? ? ? ? ? 第一种,有接口情况,使用JDK动态代理

创建接口实现类代理方法,增强类的方法

? ? ? ? ? ? ? ? 第二种,没有接口情况,使用CGLIB动态代理

创建子类的代理对象,增强类方法

?2、使用JDK动态代理,使用Proxy类里面的方法创建代理对象

(1)、调用newProxyInstance方法

?方法有三个参数:

????????ClassLoader?loader:类加载器

? ? ? ??<?>[]?interfaces:增强方法所在的类,这个类实现的接口,支持多个接口

?????????InvocationHandler?h:实现这个接口InvocationHandler,创建代理对象,写增强的方法。

有接口的情况具体代码

package com.atguigu.spring5;

public interface UserDao {
    public int add(int a,int b);
    public String update(String id);
}
package com.atguigu.spring5;

public class UserDaoImpl implements UserDao{

    @Override
    public int add(int a, int b) {
        return a+b;
    }

    @Override
    public String update(String id) {
        return id;
    }
}
package com.atguigu.spring5;

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

public class JDKProxy {
    public static void main(String[] args) {
        Class[] interfaces={UserDao.class};
        //可以直接写一个匿名类,也可以先写一个类UserDaoProxy实现InvocationHandler接口
//        Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
//            @Override
//            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                return null;
//            }
//        });
        UserDaoImpl userDao=new UserDaoImpl();
        UserDao dao=(UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces,new  UserDaoProxy(userDao));
        int result=dao.add(1,2);
        System.out.println("result:"+result);

    }
}
class UserDaoProxy implements InvocationHandler{
    private Object object;
    public UserDaoProxy(Object object){
        this.object=object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("-----------方法之前执行-----------"+method.getName()+":传递的参数"+ Arrays.toString(args));
        Object res=method.invoke(object,args);
        System.out.println("-----------方法之后执行-----------"+object);
        return res;
    }
}
<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 开启组件扫描 -->
    <context:component-scan base-package="com.atguigu.spring5"></context:component-scan>
</beans>

3、AOP一些专业术语

(1)、连接点:AOP类里面哪些方法可以被增强,哪些方法就是连接点

(2)、切入点:实际被增强的方法,称为切入点

(3)、通知(增强):实际增强的逻辑部分,称为通知

? ? ? ? ? ? ? ? 通知有多种类型:

? ? ? ? ? ? ? ? ? ? ? ? @Before? ? ? ? ? ? ? ? ?前置通知:方法之前执行

? ? ? ? ? ? ? ? ? ? ? ? @AfterReturning????后置通知:方法之后执行

? ? ? ? ? ? ? ? ? ? ? ? @Around????????????????环绕通知:方法之前之后都执行

? ? ? ? ? ? ? ? ? ? ? ? @AfterThrowing? ? ?异常通知:方法出现异常时执行

? ? ? ? ? ? ? ? ? ? ? ? @After? ? ? ? ? ? ? ? ? ? 最终通知:方法之后一定会执行

(4)、切面:把通知应用到切入点的过程,叫做切面

?4、AOP操作(准备)

? ? ? ? 1、Spring框架一般都是基于AspectJ*实现AOP操作

??????????????? *AspectJ不是Spring的组成部分,是独立的AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作

? ? ? ? 2、基于AspectJ实现AOP操作

? ? ? ? ? ? ? ? (1)、基于XML配置文件方式

? ? ? ? ? ? ? ? (2)、基于注解方式(常用)?

? ? ? ? 3、引入依赖

? ? ? ? ? ? ? ? ?Spring中:??

? ? ? ? ? ? ? ? ?单独:

? ? ? ? ? ? ? ? ?全部:

? ? ? ? ?4、切入点表达式

? ? ? ? ? ? ? ? (1)、作用:知道对哪个类里面的哪个方法进行增强

? ? ? ? ? ? ? ? (2)、写法:execution([权限修饰符*][返回类型][类全路径][方法名称]([参数列表**]))

? ? ? ? ? ? ? ? ? ? ? ? *用“*”号表示任意权限修饰符

????????????????????????**用“..”表示方法中的参数

? ? ? ? ? ? ? ? ? ? ? ? 例1:对com.atguigu.dao.BookDao类里面的add方法进行增强

?????????????????????????execution(*?com.atguigu.dao.BookDao.add(..))

? ? ? ? ? ? ? ? ? ? ? ? 例2:对com.atguigu.dao.BookDao类里面的所有方法进行增强

?????????????????????????execution(*?com.atguigu.dao.BookDao.*(..))

? ? ? ? ? ? ? ? ? ? ? ? 例3:对com.atguigu.dao包里面所有类的方法进行增强

?????????????????????????execution(*?com.atguigu.dao.*.*(..))

?5、AOP操作(AspectJ注解方式)

?被增强的类User

package com.atguigu.spring5.aopanno;

import org.springframework.stereotype.Component;

//被增强的类
@Component
public class User {
    public void add(){
        System.out.println("add.....");
    }
}

?增强类UserProxy

package com.atguigu.spring5.aopanno;

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

//增强类
@Component
@Aspect//生成代理对象
@Order(2)//设置优先级,越小优先级越高
public class UserProxy {
    //相同切入点抽取
    @Pointcut(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void pointdeom(){

    }
    //前置通知
    @Before(value = "pointdeom()")
    public void before(){
        System.out.println("before.....");
    }
    //后置通知
    @AfterReturning(value = "pointdeom()")
    public void afterReturning(){
        System.out.println("afterReturning.....");
    }
    //最终通知
    @After(value = "pointdeom()")
    public void after(){
        System.out.println("after.....");
    }
    //异常通知
    @AfterThrowing(value = "pointdeom()")
    public void afterThrowing(){
        System.out.println("afterThrowing.....");
    }
    //环绕通知
    @Around(value = "pointdeom()")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕之前.....");
        proceedingJoinPoint.proceed();
        System.out.println("环绕之后.....");
    }
}

?增强类PersonProxy

package com.atguigu.spring5.aopanno;

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

@Component
@Aspect//生成代理对象
@Order(3)//设置优先级,越小优先级越高
public class PersonProxy {
    @Before(value = "execution(* com.atguigu.spring5.aopanno.User.add())")
    public void before(){
        System.out.println("PersonProxy before");
    }
}

配置文件?

<?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:context="http://www.springframework.org/schema/context"
       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/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 开启组件扫描 -->
    <context:component-scan base-package="com.atguigu.spring5.aopanno"></context:component-scan>
    <!--开启Aspect生成代理对象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

?测试类

package com.atguigu.spring5.test;

import com.atguigu.spring5.aopanno.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAop {
    @Test
    public void testAopAnno(){
        ApplicationContext context= new ClassPathXmlApplicationContext("bean1.xml");
        User user = context.getBean("user", User.class);
        user.add();
    }
}

控制台

环绕之前.....
before.....
PersonProxy before
add.....
环绕之后.....
after.....
afterReturning.....

进程已结束,退出代码为 0

??6、AOP操作(AspectJ配置文件方式)

被增强的类Book

package com.atguigu.spring5.aopxml;

public class Book {
    public void buy(){
        System.out.println("buy......");
    }
}

增强类BookProxy?

package com.atguigu.spring5.aopxml;

public class BookProxy {
    public void Before(){
        System.out.println("Book before");
    }
}

?配置文件

<?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:context="http://www.springframework.org/schema/context"
       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/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--创建对象-->
    <bean id="book" class="com.atguigu.spring5.aopxml.Book"></bean>
    <bean id="bookProxy" class="com.atguigu.spring5.aopxml.BookProxy"></bean>
    <!--aop增强-->
    <aop:config>
        <!--切入点-->
        <aop:pointcut id="p" expression="execution(* com.atguigu.spring5.aopxml.Book.buy(..))"/>
        <!--配置切面-->
        <aop:aspect ref="bookProxy">
            <!--增强作用在具体方法上-->
            <aop:before method="Before" pointcut-ref="p"/>
        </aop:aspect>
    </aop:config>
</beans>

测试类?

package com.atguigu.spring5.test;

import com.atguigu.spring5.aopxml.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAop {
    @Test
    public void testAopXml(){
        ApplicationContext context= new ClassPathXmlApplicationContext("bean2.xml");
        Book book = context.getBean("book", Book.class);
        book.buy();
    }
}
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-22 20:26:08  更:2022-02-22 20:29:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:46:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码