【Spring框架】全集详解

article/2025/9/15 15:47:18

文章目录

    • ClassPathXmlApplicationContext工作原理
    • 01、IOC:控制反转
    • 02、什么是bean
    • 03、DI注入以及c、p命名空间
      • ```p命名空间、c命名空间```
      • ```测试各种类型的注入```
    • 04、Autowired:自动装配
    • 05、注解:Annotation
      • @Component注解的作用
      • @Repository
      • @Service
      • @Controller
    • 06、Java配置类:JavaConfig
      • @Configuration的作用
      • @Bean的作用
      • @componentscan的作用
      • @Import的作用
      • @PropertySource("db.properties")
    • 07、代理模式(静态、动态):Proxy_Mode
      • 静态代理模式示例一
      • 静态代理模式示例二
      • 动态代理模式实例三
      • 动态代理模式实例四
    • 08、AOP
      • AOP核心概念
      • AOP:切点表达式
      • AOP:使用切点表达式@annotation
      • 通知分类
      • 获取被增强方法相关信息
      • 【不使用自动注入】AOP方式一:使用配置文件方法
      • 【不使用自动注入】AOP方式二:自定义切点
      • 【不使用自动注入】AOP方式三:使用注解方法
    • 09、Spring整合Mybatis
      • 1.配置数据源文件:在resources目录下创建db.properties
      • 2.编写mybatis-config.xml文件
      • 3.编写spring-dao.xml配置文件
      • 4.将mybati以及spring整合在一个ApplicationContext.xml
    • 10、Transaction

ClassPathXmlApplicationContext工作原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gEYjiFyg-1649854715275)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220409153749314.png)]

创建一个ClassPathXmlApplicationContext类

package com.qx;import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;/*** @author : k* @Date : 2022/4/9* @Desc :*/
public class ClassPathXmlApplicationContext {private static Map<String,Object> beanMap = new HashMap<>();private String filePath;public ClassPathXmlApplicationContext(String filePath){this.filePath = filePath;load();}private void load(){try {//获取resources目录下的.xml文件  beans.xmlString path = ClassPathXmlApplicationContext.class.getClassLoader().getResource(filePath).getPath();//将我们的路径编码设置为utf-8  否则会出现乱码path = URLDecoder.decode(path,"utf-8");//解析path  修改为正常的路径  D:/Java学习/Spring/spring_00_IOD/target/classes/beans.xmlDocument document = Jsoup.parse(new File(path), "utf-8");//使用document里边的方法 通过获取元素标签的方法 取得  beans.xml文件中的bean标签//<bean class="com.qx.dao.impl.UserDaoImpl2" id="userDao"/>Elements beans = document.getElementsByTag("bean");//判断获取到的beans是否为空,如果为空则不执行if (beans != null&& beans.size()>0){for (int i = 0;i<beans.size();i++){//遍历所有的bean标签Element bean = beans.get(i);//获取bean标签中的class和id值//获取bean标签中的属性  bean.attr("class");  获取标签中的class属性// bean.attr("id"); 获取标签中id属性String className = bean.attr("class");//com.qx.dao.impl.UserDaoImpl* 全类名String id = bean.attr("id");//userDao//通过反射创建对应类的对象  反射可以使用当前文件下的绝对路径(com.qx.dao.impl.UserDaoImpl*) 获取到这个类Class<?> clazz = Class.forName(className);Constructor<?> constructor = clazz.getConstructor();//获取这个类里边的构造方法Object obj = constructor.newInstance();//调用里边的构造方法 去构造对象   即new出这个构造方法//把id作为key 创建出来的对象作为value存入map中beanMap.put(id,obj);}}} catch (Exception e) {e.printStackTrace();}}/*** 根据id从容器中获取对应的对象* @param id* @return*/public Object getBean(String id){return beanMap.get(id);//根据id从map中取得value}}

创建UserDao

package com.qx.dao;/*** @author : k* @Date : 2022/4/9* @Desc :*/
public interface UserDao {String getUserNameById(Integer id);
}

创建UserDao实现类

package com.qx.dao.impl;import com.qx.dao.UserDao;/*** @author : k* @Date : 2022/4/9* @Desc :*/
public class UserDaoImpl1 implements UserDao {@Overridepublic String getUserNameById(Integer id) {return "qx111";}
}
package com.qx.dao.impl;import com.qx.dao.UserDao;/*** @author : k* @Date : 2022/4/9* @Desc :*/
public class UserDaoImpl2 implements UserDao {@Overridepublic String getUserNameById(Integer id) {return "qx222";}
}

创建beans.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"><!--    <bean class="com.qx.dao.impl.UserDaoImpl1" id="userDao"/>--><bean class="com.qx.dao.impl.UserDaoImpl2" id="userDao"/>
</beans>

测试

package com.qx;import com.qx.dao.UserDao;
import com.qx.dao.impl.UserDaoImpl2;/*** @author : k* @Date : 2022/4/9* @Desc :*/
public class Demo {public static void main(String[] args) {ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");//获取bean中的id属性值UserDao UserDao = (UserDao) classPathXmlApplicationContext.getBean("userDao");System.out.println(UserDao.getUserNameById(1));//        UserDao userDao = new UserDaoImpl1();}
}

01、IOC:控制反转

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wC0y9z7u-1649854715276)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220309235207381.png)]

什么是IOC?

举个例子,我们有一个UserDao接口类,并且有三个UserDao实现类,分别是MysqlUserDaoImpl、OracleUserDaoImpl、UserDaoImpl,都实现UserDao接口,接下来我们编写service层的UserService接口,并且编写UserService实现类UserServiceImpl,如果根据传统的方法去调用dao层的三个实现类来实现其中的方法

我们需要写三遍以下代码

UserServiceImpl userService = new UserServiceImpl();userService.setUserDao(new MysqlUserDaoImpl());
userService.getUser();userService.setUserDao(new OracleUserDaoImpl());
userService.getUser();userService.setUserDao(new UserDaoImpl());
userService.getUser();

但是现在,我们不用传统的方法去调用,而是在UserService实现类中set dao层中的UserDao接口类

public class UserServiceImpl implements UserService{private UserDao userDao;public void setUserDao(UserDao userDao) {this.userDao = userDao;}@Overridepublic void getUser() {userDao.getUser();}
}

然后将我们的dao层中三个接口实现类通过bean交给spring容器托管,并且将Service的实现类也交给spring容器接管

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><bean id="mysqlImpl" class="com.kk.dao.MysqlUserDaoImpl"/><bean id="oracleImpl" class="com.kk.dao.OracleUserDaoImpl"/><bean id="userDaoImpl" class="com.kk.dao.UserDaoImpl"/><bean id="UserServiceImpl" class="com.kk.service.UserServiceImpl">
<!--        ref 引用Spring容器中创建好的对象value 具体的值,基本数据类型
--><!--在UserServiceImpl创建UserDao,将UserDao引入 因此UserServiceImpl有这么一个UserDao的属性  name="userDao",使用ref引用UserDao的三个实现类--><property name="userDao" ref="mysqlImpl"/>
<!--        <property name="userDao" ref="oracleImpl"/>-->
<!--        <property name="userDao" ref="userDaoImpl"/>--></bean></beans>

这时如果我们想要使用dao层中三个接口实现类中的某一个实现类,我们只需要 <property name="userDao" ref="userDaoImpl"/> 使用这个工具的ref选择我们想要实现的实现类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-og5Tg0uW-1649854715277)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220409153206111.png)]

前提是我们必须在service接口实现类中有set dao的接口

package com.kk.service;
import com.kk.dao.UserDao;
public class UserServiceImpl implements UserService{private UserDao userDao;public void setUserDao(UserDao userDao) {this.userDao = userDao;}@Overridepublic void getUser() {userDao.getUser();}
}

代码如下:

UserDao

package com.kk.dao;public interface UserDao {public void getUser();}

MysqlUserDaoImpl

package com.kk.dao;public class MysqlUserDaoImpl implements UserDao{@Overridepublic void getUser() {System.out.println("Mysql获取用户数据");}
}

OracleUserDaoImpl

package com.kk.dao;public class OracleUserDaoImpl implements UserDao{@Overridepublic void getUser() {System.out.println("Oracal获取用户数据");}
}

UserDaoImpl

package com.kk.dao;public class UserDaoImpl implements UserDao{@Overridepublic void getUser() {System.out.println("获取用户数据");}
}

UserService

package com.kk.service;public interface UserService {public void getUser();
}

UserServiceImpl

package com.kk.service;import com.kk.dao.UserDao;public class UserServiceImpl implements UserService{private UserDao userDao;//IOC  控制反转public void setUserDao(UserDao userDao) {this.userDao = userDao;}@Overridepublic void getUser() {userDao.getUser();}
}

beans.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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><bean id="mysqlImpl" class="com.kk.dao.MysqlUserDaoImpl"/><bean id="oracleImpl" class="com.kk.dao.OracleUserDaoImpl"/><bean id="userDaoImpl" class="com.kk.dao.UserDaoImpl"/><bean id="UserServiceImpl" class="com.kk.service.UserServiceImpl">
<!--        ref 引用Spring容器中创建好的对象value 具体的值,基本数据类型
--><!-- 想要使用哪一个实现类ref就指向哪一个  -->     <property name="userDao" ref="mysqlImpl"/></bean></beans>

测试:

public class Test {public static void main(String[] args) {//获取ApplicationContext 拿到Spring的容器ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");//拿到容器之后 需要什么就get即可UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl");userServiceImpl.getUser();}
}

以上便是IOC的思想,化繁为简,使用传统的去实现这个功能,需要不断的改变测试类的代码,然而使用IOC控制反转,只需改bean.xml中的代码即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zP6Cuwaf-1649854715277)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220309235207381.png)]

02、什么是bean

在Spring 中,构成应用程序主干并由Spring IoC容器管理的对象称为bean。bean是一个由Spring IoC容器实例化、组装和管理的对象。

我们总结如下:
1.bean是对象,一个或者多个不限定
2.bean由Spring中一个叫IoC的东西管理
3.我们的应用程序由一个个bean构成

比如我们建立一个实体类Hello

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Hello {private String str;
}

将这个类在beans.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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><bean id="hello" class="com.kk.pojo.Hello"><!--    set注入 获取Hello中的属性str 并且给str赋值Spring--><property name="str" value="Spring"/></bean></beans>

使用Spring创建对象,在Spring中 这些都称为Bean

类型 变量名 = new 类型

Hello hello = new Hello()
bean id = new 对象()

id=变量名
class = new 的对象((Hello))

property 相当于给对象中的属性设置值

其核心就是,给属性str使用set进行赋值

 public void setStr(String str) {this.str = str;
}

测试:

public class Test {public static void main(String[] args) {//获取Spring的上下文对象 获取其中resources目录下的beans.xml文件ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");Hello hello = (Hello) context.getBean("hello"); //获取bean中参数id为helloSystem.out.println(hello.toString());}
}

获取Spring的上下文对象,使用getBean获得bean中的id,即可获得Hello这个对象并且获得赋给ta的值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OQGdv0LA-1649854715278)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220309235849209.png)]


03、DI注入以及c、p命名空间


编写实体类

Address

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Address {private String address;}

Student

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {private String name;private Address address;private String[] books;private List<String> hobbys;private Map<String, String> card;private Set<String> games;private String wife;private Properties info;}

User

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private String name;private int age;}

将实体类都注入到bean中,编程一个个bean

p命名空间、c命名空间

userbean.xml 用于将实体类User注入到spring容器中,交给spring托管

<?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:p="http://www.springframework.org/schema/p"xmlns:c="http://www.springframework.org/schema/c"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><!--    p 命名空间注入,可以直接注入属性的值 property--><bean id="user" class="com.kk.pojo.User" p:name="王五" p:age="22"/><!--    c 命名空间注入  需要构造器  construct-args -->
<!--    singleton 单例模式  Spring的默认机制-->
<!--    prototype原型模式 每次从容器中get的时候,每一次都会产生一个新对象 --><bean id="user2" class="com.kk.pojo.User" c:name="赵六" c:age="20" scope="prototype"/></beans>

注意:需要导入以下xmlns

xmlns:p="http://www.springframework.org/schema/p

xmlns:c="http://www.springframework.org/schema/c

p命名空间

 p 命名空间注入,可以直接注入属性的值 property

c命名空间

c 命名空间注入  需要构造器  construct-args 
singleton 单例模式  Spring的默认机制
prototype原型模式 每次从容器中get的时候,每一次都会产生一个新对象 

测试各种类型的注入

仔细阅读注解

beans.xml 用于将实体类Address,Student注入到spring容器中,交给spring托管

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><bean id="address" class="com.kk.pojo.Address"><property name="address" value="广东"/></bean><bean id="student" class="com.kk.pojo.Student">
<!--        第一种:普通值注入,使用value注入--><property name="name" value="小六"/><!--        第二种:bean注入,使用ref,其中name里边的参数是写bean中的id参数--><property name="address" ref="address"/><!--        数组注入--><property name="books"><array><value>Java程序设计</value><value>SSM</value><value>微服务</value></array></property><!--        List注入--><property name="hobbys"><list><value>敲代码</value><value>赚钱</value><value>唱歌</value><value>运动</value></list></property><!--        map注入--><property name="card"><map><entry key="学号" value="2011101**"/><entry key="身份证" value="4418 **** **** ****..."/></map></property><!--        set注入--><property name="games"><set><value>CSOL</value><value>王者</value></set></property><!--        空 null 注入--><property name="wife"><null/></property><!--        Properties注入--><property name="info"><props><prop key="邮箱">30666@qq.com</prop><prop key="qq">30666</prop><prop key="性别"></prop></props></property></bean></beans>

property中的name里边的参数对应的是实体类中的属性字段


测试:

public class Test {@org.junit.Testpublic void testAddress(){ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");Address address = (Address) context.getBean("address");System.out.println(address);}public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");Student student = (Student) context.getBean("student");System.out.println(student.toString());}@org.junit.Testpublic void test2(){ApplicationContext context = new ClassPathXmlApplicationContext("userbean.xml");User user = context.getBean("user", User.class);User user2 = context.getBean("user2", User.class);System.out.println(user==user2);//结果为  false 这就是单例模式 singleton}}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L89uxAHJ-1649854715278)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220310143143176.png)]


04、Autowired:自动装配


要使用注解,首先必须开启注解支持,再beans.xml中添加以下字段

<!--    开启注解的支持--><context:annotation-config/>

编写三个实体类

Cat

public class Cat {public void shout(){System.out.println("miao~");}
}

Dog

public class Dog {public void shout(){System.out.println("wang~");}
}

People

package com.kk.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;@Data
@AllArgsConstructor
@NoArgsConstructor
@SuppressWarnings("all")
public class People {//@Resource也可以/***  @Autowired 通过byName方式实现,必须要求这个对象存在*  @Resource 默认通过byName方式实现,如果找不到名字,则通过byType方式实现*  @Qualifier 给这个注入的类指定特定的名称*  执行顺序不同*/@Autowired@Qualifier(value = "cat111")private Cat cat;@Autowired@Qualifier(value = "dog")private Dog dog;private String name;}

beans.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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!--    开启注解的支持--><context:annotation-config/><bean id="cat111" class="com.kk.pojo.Cat"/><bean id="dog" class="com.kk.pojo.Dog"/><!--    autowire  自动装配byName :会自动在容器上下文中查找和自己对象set方法后面的值 对应的beanidbyType:会自动在容器上下文中查找和自己对象属性类型(class)(com.kk.pojo.Cat)相同的bean 必须保证类型全局唯一
-->
<!--    <bean id="people" class="com.kk.pojo.People" autowire="byType">-->
<!--        <property name="name" value="赵六"/>-->
<!--        <property name="dog" ref="dog"/>-->
<!--        <property name="cat" ref="cat111"/>-->
<!--    </bean>--><bean id="people" class="com.kk.pojo.People">
<!--            给People类中的属性name赋值 qx--><property name="name" value="qx"/></bean></beans>

测试:

public class Test {@org.junit.Testpublic void test1(){ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");People people = context.getBean("people", People.class);System.out.println(people.getName());people.getDog().shout();people.getCat().shout();}
}

当我们没有使用@Autowired注解的时候,我们使用传统的方法

<bean id="cat111" class="com.kk.pojo.Cat"/>
<bean id="dog" class="com.kk.pojo.Dog"/><bean id="people" class="com.kk.pojo.People" autowire="byType"><property name="name" value="赵六"/><property name="dog" ref="dog"/><property name="cat" ref="cat111"/>
</bean>

autowire里边的参数有两个选项:
byName :会自动在容器上下文中查找和自己对象set方法后面的值,即对应的bean中的id
byType :会自动在容器上下文中查找和自己对象属性类型(class)(com.kk.pojo.Cat)相同的bean 必须保证类型全局唯一


当我们使用@Autowired注解

我们需要在people类中加上以下注解,其中@Qualifier是标注这个类在spring容器中的名字,需要一一对应

@Autowired
@Qualifier(value = "cat111")
private Cat cat;
@Autowired
@Qualifier(value = "dog")
private Dog dog;
<!--    开启注解的支持--><context:annotation-config/><bean id="cat111" class="com.kk.pojo.Cat"/><bean id="dog" class="com.kk.pojo.Dog"/><bean id="people" class="com.kk.pojo.People"/>

总结:Autowired的作用是什么?

Autowired自动装配:在People实体类中,如果我们想要调用Cat以及Dog的方法,只需将他们的类编写进来,然后在方法上加上@Autowired注解,并且在beans.xml中将它们注入到spring容器中,交给spring托管,这时我们就可以使用实体类People去调用Cat和Dog里边的方法。

相当于我们在实体类中编写实体类的方法并且使用set

@Qualifier:给bean声明一个特有的名字

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C6Z2AYBN-1649854715283)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220310150119316.png)]


05、注解:Annotation


首先不惜在spring容器配置中加上以下字段:

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!--    指定要扫描的包--><context:component-scan base-package="com.kk"/><!--    开启注解的支持--><context:annotation-config/></beans>

<context:component-scan base-package="com.kk"/> 扫面com.kk目录下所有的注解


实体类:User

@Component注解的作用

在实体类中加上@Component注解,相当于在applicationContext.xml中添加 <bean id="user" class="com.kk.pojo.User"/>

其中在实体类中的字段加上值可以使用 @Value(""),相当于 <property name="name" value="赵六"/>

 <bean id="user" class="com.kk.pojo.User"/><property name="name" value="赵六"/></bean>
//@Component 等价 于 <bean id="user" class="com.kk.pojo.User"/>
//其中id为@Component里边的参数user  @Component("user")
@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {//    @Value("赵六") 等价 于  <property name="name" value="赵六"/>@Value("赵六")public String name;}

dao层

@Repository

在dao层的接口类中,如果我们想要把其中的类交给spring容器托管,我们可以使用@Repository注解

import org.springframework.stereotype.Repository;@Repository
public interface UserDao {
}

service层

@Service

在service层的接口类中,如果我们想要把其中的类交给spring容器托管,我们可以使用@Servicea注解

@Service
public interface UserService {
}

controller层

@Controller

在controller层中,如果我们想要把其中的类交给spring容器托管,我们可以使用@Controller注解

@Controller
public class UserControl {
}

测试:

public class Test {@org.junit.Testpublic void test1(){ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");User user = context.getBean("user", User.class);System.out.println(user.getName());}
}

tip:

ClassPathXmlApplicationContext是spring读取xml最常用的类。而我们一般操作的是ta的接口ApplicationContext。BeanFactory和ApplicationContext区别不大,BeanFactory不在自动BeanPostProcessor和自动 BeanFactoryPostProcessor 上注册。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Uu6jTTV7-1649854715284)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220409211119399.png)]


06、Java配置类:JavaConfig


在spring配置中 applicationContext.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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!--    指定要扫描的包--><context:component-scan base-package="com.kk"/><!--    开启注解的支持--><context:annotation-config/></beans>

@Configuration的作用

@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

首先我在com.kk.config目录下创建一个自己的配置类 MyConfig

仔细阅读注解

  1. @Configuration类似于applicationContext.xml中的beans

  2. @Configuration 这个也会被Spring容器托管 注册到容器中 因为它本来就是一个@Component

  3. @Configuration 代表这是一个配置类,就和之前的beans.xml一样

/*** @Configuration类似于applicationContext.xml中的beans* @Configuration 这个也会被Spring容器托管 注册到容器中 因为它本来就是一个@Component* @Configuration 代表这是一个配置类,就和之前的beans.xml一样*/
@Configuration
@ComponentScan("com.kk.pojo")
@Import(MyConfig_2.class)
public class MyConfig {/*** 注册一个bean,就相当于之前写的一个bean标签* 这个方法的名字(getUser)就相当于bean标签中的id*这个方法的返回值(User)就相当于bean标签中的class属性*/@Beanpublic User getUser(){return new User();//就是返回要注入到bean的对象}}

@Bean的作用

将这个类或者方法注册到spring IoC容器中,这个配置就等同于之前在xml里的配置

<beans><bean id="getUser" class="com.kk.pojo.User"/>
</beans>
  1. 注册一个bean,就相当于之前写的一个bean标签

  2. 这个方法的名字(getUser)就相当于bean标签中的id

  3. 这个方法的返回值(User)就相当于bean标签中的class属性

    实际上是通过反射、代理来实现的

@componentscan的作用

@ComponentScan告诉Spring 哪个packages 用注解标识的类 ,会被spring自动扫描并且装入bean容器。

例如,如果你有个类用@Controller注解标识了,那么,如果不加上@ComponentScan,自动扫描该controller,那么该Controller就不会被spring扫描到,更不会装入spring容器中,因此你配置的这个Controller也没有意义。

@Import的作用

传入其他自定义配置类

@Configuration
public class MyConfig_2 {
}

测试:如果完全使用了配置类去做,就只能通过AnnotationConfig 上下文来获取容器,通过配置类的class对象加载

import com.kk.config.MyConfig;
import com.kk.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Test {public static void main(String[] args) {//如果完全使用了配置类去做,就只能通过AnnotationConfig 上下文来获取容器,通过配置类的class对象加载ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);User user = context.getBean("user", User.class);System.out.println(user.getName());}
}

@PropertySource(“db.properties”)

作用:用于在Java配置文件中读取resources目录下的db.properties文件

db.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8
user=root
password=123456

MyConfig.java

package com.kk.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.kk.pojo.User;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;@SuppressWarnings("all")
@Configuration
@PropertySource("db.properties")
public class MyConfig {@Value("${drive}")private String driverClassName;@Value("${url}")private String url;@Value("${user}")private String username;@Value("${password}")private String password;@Beanpublic DruidDataSource getDruidDataSource(){DruidDataSource druidDataSource = new DruidDataSource();druidDataSource.setDriverClassName(driverClassName);druidDataSource.setUrl(url);druidDataSource.setUsername(username);druidDataSource.setPassword(password);return druidDataSource;}}

测试:

package com.kk;
import com.kk.config.MyConfig;
import com.kk.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;import javax.sql.DataSource;/*** @author : k* @Date : 2022/4/9* @Desc :*/
public class TestMyConfigDataSource {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);DataSource bean = context.getBean(DataSource.class);System.out.println(bean);}
}

已经读取到配置文件db.properties的数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JtuX6MLE-1649854715285)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220409211305006.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zHH1mcpL-1649854715286)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220409211324059.png)]


07、代理模式(静态、动态):Proxy_Mode

在了解aop之前我们先来了解代理模式


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bXP4WS7Q-1649854715286)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220310160338177.png)]

静态代理模式示例一

租房接口类 Rent

public interface Rent {public void rent();
}

房东类 Host

public class Host implements Rent{@Overridepublic void rent() {System.out.println("房东出租房子");}
}

中介类 代理 Proxy 可以附带自己的一些属性

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Proxy implements Rent{private Host host;@Overridepublic void rent() {host.rent();seeHouse();fare();}public void seeHouse(){System.out.println("中介带你看房");}public void fare(){System.out.println("收中介费");}
}

租客类 Client

public class Client {public static void main(String[] args) {Host host = new Host();Proxy proxy = new Proxy(host);//代理,中介帮房东租房子, 代理角色一般会有一些附属操作proxy.rent();}}

静态代理模式示例二

service接口类 UserService

public interface UserService {public void add();public void delete();public void update();public void query();}

service接口实现类

public class UserServiceImpl implements UserService{@Overridepublic void add() {System.out.println("增加了一个用户");}@Overridepublic void delete() {System.out.println("删除了一个用户");}@Overridepublic void update() {System.out.println("修改了一个用户");}@Overridepublic void query() {System.out.println("查询了一个用户");}
}

代理 service实现类 UserServiceProxy

public class UserServiceProxy implements UserService{private UserServiceImpl userService;public void setUserService(UserServiceImpl userService) {this.userService = userService;}@Overridepublic void add() {log("add");userService.add();}@Overridepublic void delete() {log("delete");userService.delete();}@Overridepublic void update() {log("update");userService.update();}@Overridepublic void query() {log("query");userService.query();}//打印日志方法public void log(String msg){System.out.println("使用了"+msg+"方法");}}

用户执行

public class Client {public static void main(String[] args) {UserServiceImpl userService = new UserServiceImpl();UserServiceProxy proxy = new UserServiceProxy();proxy.setUserService(userService);proxy.add();System.out.println("==========");proxy.delete();System.out.println("==========");proxy.update();System.out.println("==========");proxy.query();}}

总结:当我们的用户想要去调用service实现类的方法的时候,这时并不直接从service实现类中取得某个方法,而是通过接口去取

注意点:需要在代理实现类 UserServiceProxy 中编写以下代码

private UserServiceImpl userService;public void setUserService(UserServiceImpl userService) {this.userService = userService;
}

当我们的用户 Client 在调用的使用只需编写以下代码

UserServiceImpl userService = new UserServiceImpl();UserServiceProxy proxy = new UserServiceProxy();proxy.setUserService(userService);proxy.add();System.out.println("==========");proxy.delete();System.out.println("==========");proxy.update();System.out.println("==========");proxy.query();

动态代理模式实例三

租房 接口 Rent

public interface Rent {public void rent();}

房东 Host 实现接口

public class Host implements Rent {@Overridepublic void rent() {System.out.println("房东出租房子");}
}

代理类 Proxy_InvocationHandler 实现 InvocationHandler接口

InvocationHandler

public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;
package com.kk.Demo03;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class Proxy_InvocationHandler implements InvocationHandler {//被代理的接口private Rent rent;public void setRent(Rent rent) {this.rent = rent;}/***  public static Object newProxyInstance(ClassLoader loader,*                                           Class<?>[] interfaces,*                                           InvocationHandler h)* *///生成得到代理类public Object getProxy(){return  Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(),this );}//处理代理实例并返回结果@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {seeHouse();fare();/*** public Object invoke(Object obj, Object... args)*///动态代理的本质就是实现反射机制Object result = method.invoke(rent, args);return result;}public void seeHouse(){System.out.println("中介带你看房");}public void fare(){System.out.println("收中介费");}
}

用户

public class Client {public static void main(String[] args) {//真实角色Host host = new Host();//代理角色Proxy_InvocationHandler handler = new Proxy_InvocationHandler();//通过调用 程序 处理  角色 来处理 要调用 的接口对象handler.setRent(host);Rent proxy = (Rent) handler.getProxy();//这里的proxy就是动态生成的,我们并没有写proxy.rent();}}

动态代理模式实例四

Proxy_InvocationHandler

package com.kk.Demo04;import com.kk.Demo03.Rent;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;@SuppressWarnings("all")
public class Proxy_InvocationHandler implements InvocationHandler {//被代理的接口private Object target;public void setTarget(Object target) {this.target = target;}//生成得到代理类public Object getProxy(){return  Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this );}//处理代理实例并返回结果@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {log(method.getName());//动态代理的本质就是实现反射机制Object result = method.invoke(target, args);return result;}public void log(String msg){System.out.println("执行了"+msg+"方法");}}

Client

package com.kk.Demo04;import com.kk.Demo02.UserService;
import com.kk.Demo02.UserServiceImpl;public class Client {public static void main(String[] args) {//真实角色UserServiceImpl userService = new UserServiceImpl();//代理角色,不存在Proxy_InvocationHandler handler = new Proxy_InvocationHandler();//设置要代理的对象handler.setTarget(userService);//动态生成代理类UserService proxy = (UserService) handler.getProxy();proxy.add();}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uSUvV1gu-1649854715287)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220310170201823.png)]


08、AOP

导包

<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.16</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.8</version></dependency>
</dependencies>

AOP核心概念

  • Joinpoint(连接点):所谓连接点是指那些可以被增强到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
  • Pointcut(切入点):所谓切入点是指被增强的连接点(方法)
  • Advice(通知/ 增强):所谓通知是指具体增强的代码
  • Target(目标对象):被增强的对象就是目标对象
  • Aspect(切面):是切入点和通知(引介)的结合
  • Proxy (代理):一个类被 AOP 增强后,就产生一个结果代理类

切入点、通知以及切面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vyViBYu5-1649854715287)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220410113317803.png)]

目标对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MrQKncsI-1649854715288)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220410113428937.png)]

AOP:切点表达式

​ 可以使用切点表达式来表示要对哪些方法进行增强。

写法:execution([修饰符] 返回值类型 包名.类名.方法名(参数))

  • 访问修饰符可以省略,大部分情况下省略
  • 返回值类型、包名、类名、方法名可以使用星号* 代表任意
  • 包名与类名之间一个点 . 代表当前包下的类,两个点 … 表示当前包及其子包下的类
  • 参数列表可以使用两个点 … 表示任意个数,任意类型的参数列表

例如:

execution(* com.sangeng.service.*.*(..))   表示com.sangeng.service包下任意类,方法名任意,参数列表任意,返回值类型任意execution(* com.sangeng.service..*.*(..))   表示com.sangeng.service包及其子包下任意类,方法名任意,参数列表任意,返回值类型任意execution(* com.sangeng.service.*.*())     表示com.sangeng.service包下任意类,方法名任意,要求方法不能有参数,返回值类型任意execution(* com.sangeng.service.*.delete*(..))     表示com.sangeng.service包下任意类,要求方法不能有参数,返回值类型任意,方法名要求已delete开头

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gFHP9evL-1649854715288)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220410152342191.png)]

在resouces目录下创建applicationContext.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"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--    指定要扫描的包--><context:component-scan base-package="com.kk"/><!--    开启注解的支持--><context:annotation-config/><!--   开启aop注解支持--><aop:aspectj-autoproxy/></beans>

创建MyAspect.java类

package com.kk.aspect;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;/*** @author :* @Date : 2022/4/9* @Desc :*/
@Component
@Aspect
public class MyAspect {//    @Pointcut("execution(* com.kk.service.*.*(..))")
//    public void pt(){
//
//    }//    @Before("pt()")
//    public void methodbefore(){
//        System.out.println("方法被调用了");
//    }//需要无参才生效
//    @Pointcut("execution(* com.kk.service..*.*())")
//    public void ptt(){
//
//    }@Pointcut("execution(* com.kk.service.*.delete*(..))")public void ptt(){}@Before("ptt()")public void methodbeforeppt(){System.out.println("方法被调用了");}}

创建service层,在service层创建UserService和PhoneService

UserService

package com.kk.service;import com.kk.aspect.InvokeLog;
import org.springframework.stereotype.Service;/*** @author : k* @Date : 2022/4/9* @Desc :*/
@Service
public class UserService {@InvokeLogpublic void qx(){System.out.println("UserService中qx的核心代码");}public void deleteAll(){System.out.println("以delete开头的");}
}

PhoneService

package com.kk.service;import com.kk.aspect.InvokeLog;
import org.springframework.stereotype.Service;/*** @author : k* @Date : 2022/4/9* @Desc :*/
@Service
public class PhoneService {@InvokeLogpublic void qx(){System.out.println("PhoneService中qx的核心代码");}
}

测试:

package com.kk;import com.kk.service.PhoneService;
import com.kk.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author : k* @Date : 2022/4/9* @Desc :*/
public class Demo {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");PhoneService phoneService = context.getBean(PhoneService.class);UserService userService = context.getBean(UserService.class);phoneService.qx();userService.qx();userService.deleteAll();}
}

AOP:使用切点表达式@annotation

我们也可以在要增强的方法上加上注解。然后使用@annotation来表示对加了什么注解的方法进行增强。

写法:@annotation(注解的全类名)

例如:

创建一个注解类InvokeLog

package com.kk.aspect;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author : k* @Date : 2022/4/10* @Desc :*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface InvokeLog {
}

在MyAspect类中使用此注解类

@Pointcut("@annotation(com.kk.aspect.InvokeLog)")

package com.kk.aspect;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;/*** @author :* @Date : 2022/4/9* @Desc :*/
@Component
@Aspect
public class MyAspect {@Pointcut("@annotation(com.kk.aspect.InvokeLog)")public void ptt(){}@Before("ptt()")public void methodbeforeppt(){System.out.println("方法被调用了");}}

UserSerice以及PhoneService

若哪个类的哪个方法需要使用aop,则在方法上面加 @InvokeLog 即可

UserSerice

package com.kk.service;import com.kk.aspect.InvokeLog;
import org.springframework.stereotype.Service;/*** @author : k* @Date : 2022/4/9* @Desc :*/
@Service
public class UserService {@InvokeLogpublic void qx(){System.out.println("UserService中qx的核心代码");}public void deleteAll(){System.out.println("以delete开头的");}
}

PhoneService

package com.kk.service;import com.kk.aspect.InvokeLog;
import org.springframework.stereotype.Service;/*** @author : k* @Date : 2022/4/9* @Desc :*/
@Service
public class PhoneService {@InvokeLogpublic void qx(){System.out.println("PhoneService中qx的核心代码");}
}

测试:

package com.kk;import com.kk.service.PhoneService;
import com.kk.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author : k* @Date : 2022/4/9* @Desc :*/
public class Demo {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");PhoneService phoneService = context.getBean(PhoneService.class);UserService userService = context.getBean(UserService.class);phoneService.qx();userService.qx();userService.deleteAll();}
}

传(img-0O4KwMJg-1649854715289)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220410152958561.png)]

通知分类

  • @Before:前置通知,在目标方法执行前执行
  • @AfterReturning: 返回后通知,在目标方法执行后执行,如果出现异常不会执行
  • @After:后置通知,在目标方法之后执行,无论是否出现异常都会执行
  • @AfterThrowing:异常通知,在目标方法抛出异常后执行
  • @Around:环绕通知,围绕着目标方法执行

其他代码不变,只需修改MyAspect中的代码即可

package com.kk.aspect;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;/*** @author :* @Date : 2022/4/9* @Desc :*/
@Component
@Aspect
public class MyAspect {@Pointcut("execution(* com.kk.service..*.*(..))")public void ptt(){}@Before("ptt()")public void methodbeforeppt(){System.out.println("before");}@AfterReturning("ptt()")public void afterReturning(){System.out.println("afterReturning");}@After("ptt()") public void after(){System.out.println("after");}@AfterThrowing("ptt()")public void afterThrowing(){System.out.println("after");}//环绕通知非常特殊,它可以对目标方法进行全方位的增强。@Around("ptt()")public void around(ProceedingJoinPoint pjp){System.out.println("around目标方法前");try {pjp.proceed();//目标方法执行System.out.println("around目标方法后");} catch (Throwable e) {e.printStackTrace();}finally {System.out.println("finally中进行增强");}}}

获取被增强方法相关信息

​ 我们实际对方法进行增强时往往还需要获取到被增强代码的相关信息,比如方法名,参数,返回值,异常对象等。

​ 我们可以在除了环绕通知外的所有通知方法中增加一个JoinPoint类型的参数。这个参数封装了被增强方法的相关信息。我们可以通过这个参数获取到除了异常对象和返回值之外的所有信息。

例如:

@Before("pt()")
public void methodbefore(JoinPoint jp){Object[] args = jp.getArgs();//方法调用时传入的参数Object target = jp.getTarget();//被代理对象MethodSignature signature = (MethodSignature) jp.getSignature();//获取被被增强方法签名封装的对象System.out.println("Before方法被调用了");
}

案例:

需求:要求让所有service包下类的所有方法被调用前都输出全类名,方法名,以及调用时传入的参数

package com.kk.aspect;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.util.Arrays;/*** @author : k* @Date : 2022/4/13* @Desc :*/
@Component
@Aspect
public class PrintLogAspect {//对哪些方法增强@Pointcut("execution(* com.kk.service..*.*(..))")public void  pt(){}//怎么增强@Before("pt()")public void printLog(JoinPoint joinPoint){//输出 被调用的方法所在的类名  方法名 调用时传入的参数MethodSignature  signature = (MethodSignature) joinPoint.getSignature();String classMethod = joinPoint.getSignature().getDeclaringTypeName();//类名 com.kk.service.UserServiceString methodName = signature.getName();//方法名   updateByIdObject[] args = joinPoint.getArgs();//调用时传入的参数 556688System.out.println(classMethod+"=="+methodName+"=="+Arrays.toString(args));}
}

​ 果需要获取被增强方法中的异常对象或者返回值则需要在方法参数上增加一个对应类型的参数,并且使用注解的属性进行配置。这样Spring会把你想获取的数据赋值给对应的方法参数。

例如:

package com.kk.aspect;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;/*** @author :* @Date : 2022/4/9* @Desc :*/
@Component
@Aspect
public class MyAspect {@Pointcut("execution(* com.kk.service..*.*(..))")public void ptt(){}@Before("ptt()")public void methodbeforeppt(JoinPoint joinPoint){MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();System.out.println(method);//public void com.kk.service.UserService.updateById(java.lang.Integer)
//        method.invoke();System.out.println("before");}@AfterReturning(value = "ptt()", returning = "ret")public void afterReturning(JoinPoint joinPoint,Object ret){System.out.println("afterReturning");}@After("ptt()")public void after(JoinPoint joinPoint){System.out.println("after");}@AfterThrowing(value = "ptt()", throwing ="t")public void afterThrowing(JoinPoint joinPoint,Throwable t){System.out.println("after");}}

​ 相信你肯定觉得上面的获取方式特别的麻烦难以理解。就可以使用下面这种万能的方法。

​ 直接在环绕通知方法中增加一个ProceedingJoinPoint类型的参数。这个参数封装了被增强方法的相关信息。

该参数的proceed()方法被调用相当于被增强方法被执行,调用后的返回值就相当于被增强方法的返回值。

例如:

package com.kk.aspect;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;/*** @author :* @Date : 2022/4/9* @Desc :*/
@Component
@Aspect
public class MyAspect {@Pointcut("execution(* com.kk.service..*.*(..))")public void ptt(){}@Around("ptt()")public void around(ProceedingJoinPoint pjp) {Object[] args = pjp.getArgs(); //获取方法参数MethodSignature signature = (MethodSignature) pjp.getSignature();Object target = pjp.getTarget(); //获取被增强的对象try {Object ret = pjp.proceed();//目标方法的执行//ret就是被增强方法的返回值System.out.println(ret);} catch (Throwable e) {e.printStackTrace();System.out.println(e.getMessage());}System.out.println(pjp);}}

【不使用自动注入】AOP方式一:使用配置文件方法

功能:要求代码在执行的时候添加日志并且打印出日志信息,当不改变业务的源代码

编写两个日志类

Log 实现MethodBeforeAdvice

public class Log implements MethodBeforeAdvice {/***	void before(Method method, Object[] args, @Nullable Object target) throws Throwable;* @param method 要执行的目标对象的方法,获取实现类的名字  target.getClass().getName() ,获取方法的名字method.getName()* @param args  参数* @param target   目标对象* @throws Throwable*/@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");}
}

After_Log 实现 AfterReturningAdvice

public class After_Log implements AfterReturningAdvice {/**** @param returnValue 返回值* @param method   获取方法的名字method.getName()* @param args* @param target* @throws Throwable*/@Overridepublic void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnValue);}
}

applicationContext.xml

将实现类以及两个自定义的log类注入到spring IoC容器中,由spring托管

<!--    注册bean--><bean id="userService" class="com.kk.service.UserServiceImpl"/><bean id="log" class="com.kk.log.Log"/><bean id="afterLog" class="com.kk.log.After_Log"/>

注意点:需要导入aop的约束:

xmlns:aop=“http://www.springframework.org/schema/aop”

http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--    注册bean--><bean id="userService" class="com.kk.service.UserServiceImpl"/><bean id="log" class="com.kk.log.Log"/><bean id="afterLog" class="com.kk.log.After_Log"/><!--    方式一:使用原生的Spring API接口--><aop:config>
<!--            切入点     expression表达式   execution 要执行的位置 就是这个切入点要在哪里执行 --><aop:pointcut id="pointcut" expression="execution(* com.kk.service.UserServiceImpl.*(..))"/><!--            这句话的意思就是 我们把这个log类 ( <bean id="log" class="com.kk.log.Log"/>) 切入到这个pointcut 方法里边-->
<!--       		advice-ref引用哪一个类进行切入    pointcut-ref将这个类切入到哪里-->            <aop:advisor advice-ref="log" pointcut-ref="pointcut"/><aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/></aop:config></beans>

【不使用自动注入】AOP方式二:自定义切点

自定义类 DiyPointCut

public class DiyPointCut {public void before(){System.out.println("=======方法执行前======");}public void after(){System.out.println("=======方法执行后======");}}

applicationContext.xml

将自定义类 DiyPointCut注入到spring IoC容器中,由spring托管

<!--    方式二:自定义类--><bean id="diy" class="com.kk.diy.DiyPointCut"/>
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--    注册bean--><bean id="userService" class="com.kk.service.UserServiceImpl"/>
<!--    方式二:自定义类--><bean id="diy" class="com.kk.diy.DiyPointCut"/><aop:config>
<!--        自定义切面 ref 要引用的类--><aop:aspect ref="diy">
<!--            切入点,就是在哪个地方使用aop,就是这个切入点要在哪里执行--><aop:pointcut id="point" expression="execution(* com.kk.service.UserServiceImpl.*(..))"/><!--            通知   method 就是要使用的方法(自定义类 DiyPointCut里边的方法) pointcut-ref这个方法要在哪里执行--><aop:before method="before" pointcut-ref="point"/><aop:after method="after" pointcut-ref="point"/></aop:aspect></aop:config>
</beans>

【不使用自动注入】AOP方式三:使用注解方法

通过注解编写切面

注意:需要使用@Aspect这个注解标注这个类是一个切面

自定义类 AnnotationPointCut

@Aspect  //标注这个类是一个切面
public class AnnotationPointCut {@Before("execution(* com.kk.service.UserServiceImpl.*(..))")public void before(){System.out.println("=======方法执行前======");}@After("execution(* com.kk.service.UserServiceImpl.*(..))")public void after(){System.out.println("=======方法执行后======");}//在环绕增强中,我们可以给定一个参数 代表我们要处理切入的点@Around("execution(* com.kk.service.UserServiceImpl.*(..))")public void around(ProceedingJoinPoint jp) throws Throwable {System.out.println("环绕前");//执行方法Object proceed = jp.proceed();System.out.println("环绕后");}}

applicationContext.xml

注意:需要开启注解支持

<!--开启注解支持 --><aop:aspectj-autoproxy/>
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--    注册bean--><bean id="userService" class="com.kk.service.UserServiceImpl"/><!--    方式三:--><bean id="annotationPointCut" class="com.kk.diy.AnnotationPointCut"/>
<!--开启注解支持 --><aop:aspectj-autoproxy/></beans>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zc5zg5Hi-1649854715289)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220310174116535.png)]


09、Spring整合Mybatis

导包:

<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.9</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.16</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.16</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.8</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.7</version></dependency></dependencies>

资源导出问题:

<build><resources><resource><directory>src/main/resources</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes></resource><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource></resources>
</build>

1.配置数据源文件:在resources目录下创建db.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8
username=root
password=123456

2.编写mybatis-config.xml文件

用于mybatis的配置文件

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration核心配置文件-->
<configuration><!--    重点:引入外部配置文件--><properties resource="db.properties"/><settings><!--        自带的日志文件--><setting name="logImpl" value="STDOUT_LOGGING"/><!--        开启驼峰命名转换--><setting name="mapUnderscoreToCamelCase" value="true"/><!--        显示的开启全局缓存--><setting name="cacheEnabled" value="true"/><!--        设置sql超时时间--><setting name="defaultStatementTimeout" value="3" /></settings><!--    给实体类起别名别名--><typeAliases><typeAlias type="com.kk.pojo.User" alias="User"/></typeAliases></configuration>

3.编写spring-dao.xml配置文件

用于spring配置文件,并且连接mybatis的配置文件

<?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"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!--    读取 db.properties 配置文件--><context:property-placeholder location="classpath:db.properties"/><!--    DataSource   使用Spring的数据源替换Mybatis的配置
我们这里使用Spring提供的JDBC  org.springframework.jdbc.datasource--><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>-->
<!--        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf-8"/>-->
<!--        <property name="username" value="root"/>-->
<!--        <property name="password" value="123456"/>--><property name="driverClassName" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${user}"/><property name="password" value="${password}"/></bean><!--    sqlSessionFactory    --><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><!--        绑定Mybatis配置文件--><property name="configLocation" value="classpath:mybatis-config.xml"/><property name="mapperLocations" value="classpath:com/kk/mapper/*.xml"/></bean><!--    SqlSessionTemplate 就是我们使用的sqlSession--><bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"><!--        只能使用构造器注入sqlSessionFactory,因为ta没有set方法--><constructor-arg index="0" ref="sqlSessionFactory"/></bean></beans>

4.将mybati以及spring整合在一个ApplicationContext.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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><import resource="spring_dao.xml"/><bean id="userMapper" class="com.kk.mapper.UserMapperImpl"><property name="sqlSession" ref="sqlSession"/></bean></beans>

实体类 User

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private int id;private String username;private String password;}

mapper层

UserMapper 接口

public interface UserMapper {public List<User> selectUser();}

UserMapper.xml

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.kk.mapper.UserMapper"><select id="selectUser" resultType="User">select * from mybatis.user ;</select></mapper>

接口实现类 UserMapperImpl

public class UserMapperImpl implements UserMapper{//我们的所有操作,,在原来都使用SqlSession来执行,现在都使用SqlSessionTemple;private SqlSessionTemplate sqlSession;//需要将它注入进来public void setSqlSession(SqlSessionTemplate sqlSession) {this.sqlSession = sqlSession;}@Overridepublic List<User> selectUser() {UserMapper mapper = sqlSession.getMapper(UserMapper.class);List<User> userList = mapper.selectUser();return userList;}
}

拓展:使用实现类继承SqlSessionDaoSupport

UserMapperImpl2

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{@Overridepublic List<User> selectUser() {SqlSession sqlSession = getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);List<User> userList = mapper.selectUser();return userList;}
}

在spring_dao.xml中加入以下字段

<!--    整合mybatis方式2--><bean id="userMapper2" class="com.kk.mapper.UserMapperImpl2"><property name="sqlSessionFactory" ref="sqlSessionFactory"/></bean>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F0yO6MQR-1649854715290)(C:\Users\30666\AppData\Roaming\Typora\typora-user-images\image-20220310193156529.png)]

10、Transaction

当我们在编写数据增删改的时候,如果没有设置提交事务,即使运行成功,它的数据还是不会提交到数据库中,这时我们如何在不改变业务层源代码的情况下对事务进行提交呢? AOP 切面编程

spring整合mybatis的配置文件09有,这里不再编写

但是我们需要增加aop,对增删改进行提交事务

<?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"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!--    DataSource   使用Spring的数据源替换Mybatis的配置
我们这里使用Spring提供的JDBC  org.springframework.jdbc.datasource--><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf-8"/><property name="username" value="root"/><property name="password" value="123456"/></bean><!--    sqlSessionFactory    --><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><!--        绑定Mybatis配置文件--><property name="configLocation" value="classpath:mybatis-config.xml"/><property name="mapperLocations" value="classpath:com/kk/mapper/*.xml"/></bean><!--    SqlSessionTemplate 就是我们使用的sqlSession--><bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"><!--        只能使用构造器注入sqlSessionFactory,因为ta没有set方法--><constructor-arg index="0" ref="sqlSessionFactory"/></bean><!--    ===============================================================--><!--     配置声明式事务--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!--    结合aop 实现事务的注入-->
<!--    配置事务 通知--><tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--        给哪些方法配置事务-->
<!--        配置事务的传播特性 propagation--><tx:attributes>   <tx:method name="*" propagation="REQUIRED"/></tx:attributes></tx:advice><!--    配置事务切入--><aop:config>
<!--        切入点  谁需要事务--><aop:pointcut id="txPointCut" expression="execution(* com.kk.mapper.*.*(..))"/><!--        切入  将事务切入到哪里 --><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/></aop:config></beans>

http://chatgpt.dhexx.cn/article/dVdSE7Ui.shtml

相关文章

spring 入门详解超

一.什么是spring 1.简介&#xff1a;Spring是一个开源的设计层面框架&#xff0c;解决了类与类之间的彻底解耦&#xff0c;它将面向接口的编程思想贯穿整个系统应用。 2.spring核心&#xff1a; IOC&#xff08;Inverse of Control 控制反转&#xff09;&#xff1a;将bean的…

Spring框架入门详解

Spring 为什么引入Spring框架 为了提高开发效率和实现模块之间的高聚合低耦合&#xff0c;所以引入了Spring框架 高聚合低耦合 高内聚 内聚是指模块内的联系&#xff0c;各个元素之间紧密联系共同完成任务&#xff0c;模块内的联系越紧密越好&#xff0c;这样可以提高他们…

Spring详解(小白教程,大佬勿入,勿喷。)

1.Spring概述 Spring是什么&#xff1f; 在resource目录下创建子包需要用/ 如&#xff1a;com/baidu/userMapper.xml Spring是分层的 Java SE/EE应用 full-stack 轻量级开源框架&#xff0c; 以 IoC&#xff08;Inverse Of Control&#xff1a;反转控制&#xff09;和 AOP&…

spring aop详解

1.前言 spring aop是一个面向切面的编程&#xff0c;在自己第一遍学习的时候&#xff0c;感觉aop没有什么作用&#xff0c;但是真实接触下来&#xff0c;感觉spring aop还是很有用途的&#xff0c;感觉自己之前的想法太年轻了。 2.概念 Spring 提供了两种AOP 的实现&#xf…

详解Spring

Spring SSH框架中Struts2:是基于Web层&#xff0c;Hibernate&#xff1a;是基于持久化的&#xff0c;Spring:业务层&#xff0c;管理bean&#xff0c;它是一个容器&#xff0c;List,map&#xff0c; Set这里的内容&#xff0c;是适合已经学过了Spring的人供复习参考的..... Spr…

Spring详解简介

1、Spring的简介 Spring的英文翻译为春天&#xff0c;可以说是给Java程序员带来了春天&#xff0c;因为它极大的简化了开发。我得出一个公式&#xff1a;Spring 春天 Java程序员的春天 简化开发。最后的简化开发正是Spring框架带来的最大好处。 Spring是一个开放源代码的设计…

spring 详细讲解

有人说&#xff0c;“Java程序员都是Spring程序员”&#xff0c;老三不太赞成这个观点&#xff0c;但是这也可以看出Spring在Java世界里举足轻重的作用。 基础 1.Spring是什么&#xff1f;特性&#xff1f;有哪些模块&#xff1f; Spring Logo 一句话概括&#xff1a;Spring…

JAVA框架Spring 全面详解(学习总结)

Spring 1.Spring 全面详解 1.1简介 ◆ Spring&#xff1a;春天 给软件行业带来了春天 ◆ 2002&#xff0c;首次推出了Spring框架的雏形&#xff1a;interface21框架 ◆ Spring框架即是以interface21框架为基础经过重新设计&#xff0c;并不断丰富其内涵&#xff0c;于2004…

Spring的事务详解

事务简介 事务在逻辑上是一组操作&#xff0c;要么执行&#xff0c;要不都不执行。主要是针对数据库而言的&#xff0c;比如说 MySQL。 为了保证事务是正确可靠的&#xff0c;在数据库进行写入或者更新操作时&#xff0c;就必须得表现出 ACID 的 4 个重要特性&#xff1a; 原…

java系列之Spring详解

一、Spring简介 1.1 简介 关于spring的简介&#xff0c;可以查看百度百科&#xff0c;下面内容部分来自百度百科 Spring框架是针对软件开发过程中的复杂性而创建的。其使用javaBean来完成以前只可能由EJB完成的事情。 2002年&#xff0c;Rod Jahnson首次推出了Spring框架雏形…

Spring全面详解

—————版本Spring5.x————— ——编译器IntelliJ IDEA 2020.2.3 —— <-- 该文章有点老旧&#xff0c;停止了更新&#xff0c;请查看Spring5最新文章&#xff0c;目前已经书写完成 --> Spring5全面详解 它会持续更新&#xff0c;你所看到的不是最终版本。 如…

Spring-全面详解(学习总结)

Spring 1.简介 1.1.简介 简介 Spring : 春天 —>给软件行业带来了春天 2002年&#xff0c;Rod Jahnson首次推出了Spring框架雏形interface21框架。 2004年3月24日&#xff0c;Spring框架以interface21框架为基础&#xff0c;经过重新设计&#xff0c;发布了1.0正式版。 …

spring超全面详解

spring概述 Spring 是于2003年兴起的一款轻量级的,非侵入式的IOC和AOP的一站式的java开发框架 为简化企业级应用开发而生. 1.轻量级: 就是指spring核心功能的jar包不大 2.非侵入式: 我们的业务代码不需要继承或实现spring中任何的类或接口 3.IOC: 控制反转 就是把创建…

Spring全面详解(学习总结)

Spring FrameWork一、 前言二、IOC(控制反转)2.1 对于IOC的理解2.2如何使用IOC2.3配置文件的解读2.4IOC容器创建bean的两种方式2.5从IOC容器中取bean2.6bean的属性如果包含特殊字符 三、DI(依赖注入)四、Spring中的bean五、Spring中的继承六、Spring的依赖七、Spring读取外部资…

查看Linux的用户权限(转载)

&#xff08;转&#xff09;Linux查看用户及其权限管理 查看用户 请打开终端&#xff0c;输入命令&#xff1a; $ who am i或者 $ who mom likes输出的第一列表示打开当前伪终端的用户的用户名&#xff08;要查看当前登录用户的用户名&#xff0c;去掉空格直接使用 whoami …

linux查看登录用户

1&#xff0c;w w,显示目前登入系统的用户信息 -f  开启或关闭显示用户从何处登入系统。 -h  不显示各栏位的标题信息列。 -l  使用详细格式列表&#xff0c;此为预设值。 -s  使用简洁格式列表&#xff0c;不显示用户登入时间&#xff0c;终端机阶段作业和程序所耗费…

Linux下查看当前用户和所属用户组方法总结

1、查看当前用户 &#xff08;1&#xff09;whoami &#xff08;2&#xff09;id -un &#xff08;3&#xff09;who -H &#xff08;4&#xff09;who&#xff08;查看当前登陆的所有用户&#xff0c;和who -H功能差不多&#xff09; 2、查看当前用户所属的组 &#xff08…

linux如何查看所有的用户和组信息?

首先打开终端&#xff08;这里是Ubuntu系统&#xff09;&#xff0c;其他的打开命令界面即可 然后输入命令行cat /etc/passwd&#xff0c;直接按下回车键即可 然后这里就会显示很多的信息&#xff0c;所有的用户都在这里面了 然后就是查看所有的组&#xff0c;同样的方法…

linux 查看用户信息

目录 /etc/passwd id命令 whois命令 whoami命令 who命令 w命令 finger命令 vlock命令 /etc/passwd 有的用户信息在根目录 /etc/passwd 文件内&#xff0c;而passwd的所有权限是root用户及root组用户&#xff0c;所有想要查看所有用户&#xff0c;需要root用户登录系统…

linux查看所有用户命令

1、Linux里查看所有用户 (1)在终端里.其实只需要查看 /etc/passwd文件就行了. (2)看第三个参数:500以上的,就是后面建的用户了.其它则为系统的用户. 或者用cat /etc/passwd |cut -f 1 -d : 2、用户管理相关命令 useradd命令 useradd 选项 用户名 -d 目录,指定用户主目录,如…