入门 Spring
- Spring 官方网址:spring.io
- 导入 Jar 包
- IoC:控制反转 :对象不是由自己创建,而是由 Spring 容器来创建
- 创建对象方式—XML 方式
- applicationContext.xml—配置文件
<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">
<!--配置对象
- name 别名, 可以用 「,」 和 「 」 隔开
- lazy-init="true" 懒加载
- scope="prototype" prototype 多例 (默认是单例) 表示该 Bean 的作用域为多例。每次请求该 Bean 时,都会创建一个新的实例
-->
<bean id="user" class="pojo.User" name="dud,sos kok" lazy-init="true" scope="prototype"/>
<alias name="user" alias="person,people kin" /><!-- 别名 ( 可以配置多个别名 ) -->
</beans> - 两种方式来创建 IoC 对象 public class MyTest {
@Test
public void test(){
// 加载配置文件 创建 IOC 容器 (相对路径)
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml", "applicationContext.xml");
// 获取配置创建的对象
User user = (User) context.getBean("user");
System.out.println(user.toString());
}
@Test
public void test2(){
// 加载配置文件 创建 IOC 容器 (绝对路径)
ApplicationContext context2 = new FileSystemXmlApplicationContext("D:\\JavaWeb\\2024_Spring\\spring\\hellospring\\src\\main\\resources\\application.xml");
User user2 = context2.getBean("user",User.class);
System.out.println(user2.toString());
}
}
DI 依赖注入
- 依赖什么?注入什么?
- 依赖注入指在对象创建时设置初始值
- 依赖:bean 对象创建依赖于容器
- 注入:指的是 bean 对象由容器来设置和装配 (初始化)
- 第一种:构造器注入<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="pojo.User" p:name="shizhishi">
<!-- 依赖注入
- constructor-arg 是 通过构造器参数注入依赖 对象创建时就需要确定的
-->
<constructor-arg name="name" value="shizhishi" />
<constructor-arg name="age" value="18"/>
<constructor-arg name="email" value="null" />
<constructor-arg name="address" value="杭州" />
<constructor-arg name="phone" value="null" />
<!-- 构造器注入方式 2 -->
<constructor-arg index="0" value="shizhishi" />
<constructor-arg index="1" value="18"/>
<!-- 构造器注入方式 3 -->
<constructor-arg type="java.lang.String" value="shizhishi" />
<constructor-arg type="int" value="18"/>
</bean>
</beans> - 第二种:Setter 方式注入<?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/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 依赖注入
- property 是 通过 setter 方法注入依赖 对象创建后可以通过 setter 方法设置
-->
<bean id="address" class="pojo.Address">
<!-- 常量注入-->
<property name="city" value="杭州" />
</bean>
<bean id="user" class="pojo.User" />
<bean id="student" class="pojo.Student">
<!-- 常量注入-->
<property name="name" value="shizhishi" />
<!-- 引用其他 bean-->
<!-- <ref bean="address" /> -->
<property name="address" ref="address">
</property>
<!-- 数组注入-->
<property name="powers">
<array>
<value> 时间</value>
<value> 空间</value>
</array>
</property>
<!-- 集合注入-->
<property name="list">
<list>
<value> 时间</value>
<value> 空间</value>
</list>
</property>
<!-- map 注入-->
<property name="map">
<map>
<entry key="1" value="时间" />
<entry key="2" value="空间" />
</map>
</property>
<property name="properties">
<props>
<prop key="1"> 时间</prop>
<prop key="2"> 空间</prop>
</props>
</property>
</bean>
</beans> - 第三种—扩展注入<!-- 配置 bean
- P: 通过 p 命名空间注入属性
- 是一种简化了的依赖注入方式,直接在<bean> 标签内使用属性名前缀 p: 来定义依赖。
- 主要用于 setter 注入,不需要额外的<property> 标签。
-->
<bean id="user" class="pojo.User" p:name="shizhishi">
<!--
- c: c 命名空间与 p: 命名空间类似,但 p: 命名空间更常用,p: 命名空间是 Spring 的默认命名空间,所以可以不用写。
- c: 的作用是:主要用于通过构造函数进行依赖注入。
-->
<bean id="address" class="pojo.Address" c:city="北京">
<!--
- 可选性: 使用 c 命名空间时,一次注入所有依赖。而 p 命名空间允许选择依赖注入。
- 初始化顺序: 由于 c 命名空间是通过构造函数注入,所以依赖项会在对象实例化时就确定下来。而 p 命名空间则是在对象实例化后通过 setter 方法注入依赖。
--> - 自动装配 Autowire<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解支持-->
<context:annotation-config></context:annotation-config>
<bean id="user" class="pojo.User" autowire="byName">
<!--
- 自动装配:
- autowire="byName" 根据属性名进行注入 Spring 容器会尝试通过依赖的属性名称 (即 Bean 中的 setter 方法对应的属性名) 来匹配容器中已定义的 Bean 。
- autowire="byType" 根据属性类型进行注入 不适用于存在多个相同类型的属性
- autowire="constructor" 根据构造函数进行注入
- 手动装配
- 加入 property 标签,手动注入
-->
<property name="name" value="时之世"/>
<property name="cat" ref="cat"/>
<property name="cat1" ref="cat"/>
<property name="dog" ref="dog"/>
</bean>
</beans> - 注解/**
* Autowired: 自动装配,通过类型匹配,如果匹配到多个,则通过属性名匹配
* required: 是否必须,默认为 true,如果为 false,则表示这个属性不是必须的,如果匹配不到,则不报错,直接为 null
* Qualifier: 指定 bean 的 id,如果 Autowired 匹配不到,则通过 Qualifier 匹配
* */
@Autowired(required = false)
@Qualifier("cat1")
private Cat cat1;
private Cat cat;
/**
* Resource: 自动装配 通过名称匹配, 如果匹配到多个,则通过属性名匹配, 是 jdk 自带的注解
* */
@Resource(name = "dog")
private Dog dog;
Java Annotation
自定义注解 (包含三个不同的作用域)
/**
* @author shizhishi
*/ //定义一个注解
@Target(ElementType.TYPE)//类上
@interface Myannotation {
//注解的属性
String name();
}
/**
* @author shizhishi
*/
@Target(ElementType.METHOD)//方法上
@interface Myannotation1 {
//注解的属性
String name();
}
/**
* @author shizhishi
*/
@Target(ElementType.FIELD)//属性上
@interface Myannotation2 {
//注解的属性
String name();
}
@Myannotation(name = "zhangsan")
public class TextAnnotation {
@Myannotation2(name = "wangwu")
private String name;
@Myannotation1(name = "lisi")
void test() {
}
}
通过反射获取注解上的值
// 通过反射获取注解信息
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
// Class c = Class.forName("StudentDao");
//或
Class c = StudentDao.class;
Annotation[] annotations = c.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
//result: @Select("111111")
}
//获取类上注解的 Value 值
Select select = (Select) c.getAnnotation(Select.class);
System.out.println(select.value());
//result: 111111
//获取方法上的注解
Method methods = c.getDeclaredMethod("findAll");
Select select1 = methods.getAnnotation(Select.class);
System.out.println(select1.value());
}
Spring Annotation
- 第一步:扫描包 <!--自动装配-->
<context:annotation-config />
<!--扫描包-->
<context:component-scan base-package="com.niit.*" /> - 基本的注解
@Component
把普通 pojo 实例化到 spring 容器中,相当于配置文件中的<bean id="" class=""/>@Controller
控制层 (web),效果等同于@Component
@Service
业务层,效果等同于@Component
@Respository
持久层,效果等同于@Component
无配置文件开发:基于 Java 类
- 主要是对比 applicationContext.xml 配置文件/**
* @author shizhishi
* Configuration 注解表示当前类是一个配置类,相当于 spring 的配置文件
*/
@Configuration
@ComponentScans({ @ComponentScan(value = {"service","pojo"})})// 扫描包,相当于之前写的<context:component-scan base-package="service,pojo"/>
public class MyConfig {
//最基本的配置,注册一个 bean,就相当于我们之前写的一个 bean 标签
// @Bean
// public Student getStudent(){
// return new Student();
// } - 不同类型的 bean@Test
public void test() {
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
// 基本类型的 bean
// Student student = context.getBean("getStudent", Student.class);
// 引用类型的 bean
Student student = context.getBean("student", Student.class);
System.out.println(student.name);
}
AOP 面向切面编程
- 切面和切点
- 切面:是通知和切点的集合,定义了
- 切点:缩小了切面的内容,可以指定在匹配的方法上执行哪些通知
- aop java 自带接口
- MethodBeforeAdvice :前置通知
- AfterReturningAdvice :后置通知
- DynamicIntroductionAdvice :环绕通知
- ThrowsAdvice :异常通知
- 导入 Jar 包<!-- 导入切面编程的依赖包 (植入包)-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency> - 配置切面 (启用 jdk 动态代理)<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="studentService" class="aop.StudentServiceImpl"/>
<bean id="logBefore" class="aop.LogBefore"/>
<bean id="logAfter" class="aop.LogAfter"/>
<!-- 配置切面 -->
<!-- <aop:aspectj-autoproxy proxy-target-class="true"/>
- proxy-target-class 默认为 false,表示使用 jdk 动态代理,设置为 true 表示使用 cglib 动态代理。
- 默认情况下,Spring AOP 是基于动态代理实现的,当目标对象实现了接口,Spring AOP 会使用 JDK 动态代理;当目标对象没有实现接口,Spring AOP 会使用 CGLIB 动态代理。
-->
<aop:aspectj-autoproxy>
<aop:include name="logBefore"/>
<aop:include name="logAfter" />
</aop:aspectj-autoproxy>
<!-- 配置切点 -->
<aop:config>
<!--
定义一个 AOP 切点 studentServicePointcut
作用:此切点用于匹配 aop 包下的 StudentService 类中的所有方法调用。
* 表示返回类型任意,aop.StudentService 表示指定类,.*(..) 表示类中的所有方法及任意参数。
-->
<aop:pointcut id="studentServicePointcut" expression="execution(* aop.StudentService.*(..))"/>
<!--
配置 AOP 切面以应用前置通知到特定的服务方法上。
参数:
advice-ref: 指定名称为 logBefore 的前置通知,该通知会在切点定义的方法被调用之前执行。
pointcut-ref: 指定名称为 studentServicePointcut 的切点,该切点定义了哪些方法会被 advice-ref 指定的通知所拦截。
作用:
当匹配 studentServicePointcut 定义的方法被调用时,系统将首先执行 logBefore 通知中的逻辑。
-->
<aop:advisor advice-ref="logBefore" pointcut-ref="studentServicePointcut"/>
<aop:advisor advice-ref="logAfter" pointcut-ref="studentServicePointcut"/>
</aop:config>
</beans> - 配置切面 (指定代理目标类)@Component
public class DiyPointCut {
public void before(){
System.out.println("before");
}
public void after(){
System.out.println("after");
}
public void around(){
System.out.println("around");
}
}<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<aop:config proxy-target-class="true"><!--指定代理目标类-->
<aop:aspect ref="diyPointCut">
<!--切点-->
<aop:pointcut id="pointCut" expression="execution(* aop2.StudentServiceImpl.*(..))"/>
<!--通知-->
<aop:before method="before" pointcut-ref="pointCut"/>
<aop:after method="after" pointcut-ref="pointCut"/>
</aop:aspect>
</aop:config>
</beans> - 使用注解开发/**
* @author shizhishi
*/
@Component
@Aspect
public class AnnotationPointCut {
@Before("execution(* aop2.StudentServiceImpl.*(..))")
public void before(){
System.out.println("AnnotationPointCut.before");
}
@After("execution(* aop2.StudentServiceImpl.*(..))")
public void after(){
System.out.println("AnnotationPointCut.after");
}
@Around("execution(* aop2.StudentServiceImpl.*(..))")
public Object around(ProceedingJoinPoint pjp){
System.out.println("AnnotationPointCut.around");
return null;
}
}
Comments NOTHING