Spring5 入门
spring 介绍
- IOC 解耦对象,对象间无直接联系,有 IOC 容器进行管理-
- 类创建对象有 IOC 完成,这就是控制反转 IOC
IOC 与 DI 是同一件事情的不同描述。
- DI 应用程序依赖容器创建并注入他所需要的外部资源
- IOC 容器控制程序
Spring 框架主要功能是通过其核心容器来实现的。
- spring 提供的两种核心容器分别是 BeanFactory 和 ApplicationContext.
- IOC/DI 通常有 setter 注入和构造方法注入两种实现方式
- spring 中编辑配置文件管理 Bean 又称为 Bean 的装配
- 实际上装配就是告诉容器需要哪些 Bean ,以及容器是如何使用 IOC 将他们配合起来的。
Beans 是指项目中提供业务功能的 Bean ,即容器要管理的 Bean . Beans 就是一个常见的 JavaBean ,Java类
- spring 中管理 Bean 是在配置文件中进行的
对于Spring这样的框架,(View\Web)表示层调用控制层(Controller),控制层调用业务层(Service),业务层调用数据访问层(Dao)。
具体起来,Dao的作用是封装对数据库的访问:增删改查,不涉及业务逻辑,只是达到按某个条件获得指定数据的要求;
而Service,则是专注业务逻辑,对于其中需要的数据库操作,都通过Dao去实现;
spring 入门步骤
pom 引进spring依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
</dependencies>
创建 UserDao 接口
package com.it;
public interface UserDao {
public void save();
}
实现 UserDao 接口
package com.it.impl;
import com.it.UserDao;
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("save...");
}
}
在 resources 目录创建 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDao" class="com.it.impl.UserDaoImpl"></bean>
</beans>
正式运行
package com.it.demo;
import com.it.UserDao;
import com.sun.xml.internal.org.jvnet.fastinfoset.VocabularyApplicationData;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.applet.AppletContext;
public class userDaoDemo {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) app.getBean("userDao");
userDao.save();
}
}
spring 配置文件详解
scope 属性
-
可选值 singleton , prototype
-
步骤
-
修改 Bean 属性
<bean id="userDao" class="com.it.impl.UserDaoImpl" scope="singleton"></bean>
-
新建测试类
package com.it.demo; import com.it.UserDao; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.sql.SQLOutput; public class springTest { @Test // 测试 scope 属性 public void test1() { ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao1 = (UserDao) app.getBean("userDao"); UserDao userDao2 = (UserDao) app.getBean("userDao"); System.out.println(userDao1); System.out.println(userDao2); } }
-
预期输出
com.it.impl.UserDaoImpl@3712b94 com.it.impl.UserDaoImpl@3712b94
-
-
方法属性
-
可选值有 init-method , destroy-method
-
init-method :制定 Bean 初始化时的初始化方法
-
destroy-method :对象不用时执行的销毁方法
依赖注入
实现 Dao 层注入到 Service 层,只需要操作 Service 层就能操作 Dao 层
setter 方法注入
-
创建 UserService 接口
package com.it;public interface UserService { public void save();}
-
实现 UserService 接口
package com.it.impl;import com.it.UserDao;import com.it.UserService;public class UserServiceImpl implements UserService{ private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } private UserDao getUserDao(UserDao userDao) { return userDao; } public void save() { this.userDao.save(); }}
-
创建注入依赖,注意是 ref 而不是 value
<bean id="userDao" class="com.it.impl.UserDaoImpl"/> <bean id="userService" class="com.it.impl.UserServiceImpl"> <property name="userDao" ref="userDao"/> </bean>
-
运行
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); //UserDao userDao = (UserDao) app.getBean("userDao"); UserService userService = app.getBean("userService" ,UserService.class); userService.save();
-
输出
save...
p0 方式注入
步骤(只需要在 setter 方法中修改就行)
-
在 applicationContext.xml 中引入 p0 空间
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userDao" class="com.it.impl.UserDaoImpl"/> <bean id="userService" class="com.it.impl.UserServiceImpl" p:userDao-ref="userDao"/></beans>
进行普通属性的注入
-
与对象注入一样,但是要用 value 修饰
<property name="username" value="张三" />
-
集合的注入
... private List<String> strList; private Map<String ,User> userMap;
-
xml 文件中进行注入
<!-- 类似于 c 中的 include 语句 --><import resource="name.xml"/><bean id="user1" class="com.it.User"/><bean id="user2" class="com.it.User"/><!-- 注入 List --><property name="strList"> <list> <value>aaa</value> <value>bbb</value> <value>ccc</value> </list></property><!-- 注入 Map ,其实 value 是用来注入普通类型的,比如 String , int--><property name="userMap"> <map> <entry key="user1" value-ref="user1"></entry> <entry key="user1" value-ref="user1"></entry> </map></property>
spring 数据源开发
-
步骤
- 导入数据源的坐标和数据库驱动坐标
- 创建数据源对象
- 创建数据源的基本连接数据
- 使用数据源获取连接资源和归还连接资源
-
实现
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>untitled</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> </dependency> </dependencies> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties></project>
package com.it.impl;import com.alibaba.druid.pool.DruidDataSource;import com.alibaba.druid.pool.DruidPooledConnection;import com.mchange.v2.c3p0.ComboPooledDataSource;import org.junit.Test;import java.sql.Connection;public class DataSource { @Test // c3p0 数据源创建 public void test1() throws Exception { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass("com.mysql.cj.jdbc.Driver"); dataSource.setJdbcUrl("jdbc://mysql://localhost:3306/ceshi"); dataSource.setUser("ceshi"); dataSource.setPassword("ceshi"); Connection connection = dataSource.getConnection(); System.out.println(connection); connection.close(); } @Test // druid 数据源 public void test2() throws Exception { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc://mysql://localhost:3306/ceshi"); dataSource.setUsername("ceshi"); dataSource.setPassword("ceshi"); DruidPooledConnection connection = dataSource.getConnection(); System.out.println(connection); connection.close(); }}
spring 使用注解实现自动装配
-
使用方法
-
导入约束
xmlns:context="http://www.springframework.org/schema/context"
-
配置注解的支持
<context:annotation-config/>
-
然后整个配置文件看起来就是这样
<?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:annotation-config/> <bean id="cat" class="Cat"/> <bean id="dog" class="Dog"/> <bean id="people" class="People"/></beans>
-
新建 Cat.java 和 Dog.java 文件,以及总的类 People.java
Cat.javaimport javax.xml.bind.SchemaOutputResolver;public class Cat { public void say() { System.out.println("miao~"); }}-------------------------------------------------Dog.javapublic class Dog { public void say() { System.out.println("wang~"); }}-------------------------------------------------- People.javaimport org.springframework.beans.factory.annotation.Autowired;public class People { @Autowired private Cat cat; @Autowired private Dog dog; public Cat getCat() { return cat; } public Dog getDog() { return dog; }}
-
正式开始测试
import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyTest { @Test public void test1() { ApplicationContext app = new ClassPathXmlApplicationContext("beans.xml"); People people = app.getBean("people", People.class); people.getCat().say(); }}
输出
miao~
-
-
tips
-
配合 Qualifier 注解实现选择某个 id 对应的 Bean 来进行注解
@Autowired@Qualifier(value = "cat")
也可以仅用 Resource 注解实现上面所有的事情
@Resource(name = "cat")
-
spring 注解开发
-
小案例
-
pom.xml 基本不变,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/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.it"/> <context:annotation-config/></beans>
-
User.java 文件
package com.it;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;// 等价于 <bean id="user" class="com.it"/>// @Component 组件@Componentpublic class User { // 显式进行属性的注入 // 相当于 <property name="name" value="海杰"/> @Value("海杰") public String name;}
-
开始测试
import com.it.User;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyTest { @Test public void test1() { ApplicationContext app = new ClassPathXmlApplicationContext("beans.xml"); User user = app.getBean("user" , User.class); System.out.println(user.name); }}
-
输出
海杰
-
-
tips
事实上在业务中可以用 dao: @Repository service: @Service controller: @Controller
JavaConfig 实现自动装配
-
tips
- 这是基于配置类来实现的功能
- 有点是不用再书写 Beans.xml 配置文件
- 使用后就不能用 CLX 来获取 Bean 容器,只能使用 Anno… 来获取
-
案例
-
User.java 文件
package com.it;import org.springframework.beans.factory.annotation.Value;public class User { public String name; public String getName() { return name; } @Value("海杰") public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; }}
-
JavaConfig.java 文件
package com.it;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Import;// 这个会被 spring 容器接管,注册到容器中,因为他本来就是一个 @Component// @Configuration 表示是一个配置类,就和我们之前的 beans.xml 一样的东西来的@Configuration// 指定要扫描哪个包@ComponentScan("com.it")// 把多个 JavaConfig 类合并成一个文件,类似于 c 语言中的 include 语句@Import(JavaConfig02.class)public class JavaConfig { // 注册一个 Bean ,就相当于我们之前写的一个 Bean 标签 // 这个方法中的名字就相当于 Bean 标签中的 id 属性 // 这个方法中的返回值就相当于 Bean 标签中的 class 属性 @Bean public User getUser() { // 就是返回要注入到 bean 中的对象 return new User(); }}
-
JavaConfig02.java 文件
package com.it;import org.springframework.context.annotation.Configuration;@Configurationpublic class JavaConfig02 {}
-
单元测试类
import com.it.JavaConfig;import com.it.User;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class MyTest { public static void main(String[] args) { // 如果完全使用了配置类方式去做,我们就只能通过 AnnotationConfig 上下文来获取容器,通过配置类的 class 对象加载 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class); User getUser = (User) context.getBean("getUser"); System.out.println(getUser.getName()); }}
-
输出
海杰
-
动态代理
-
tips
- 动态代理和静态代理一样都有真实对象和代理对象
- 动态代理的代理类是动态生成的,不是我们直接写好的
- JDK 动态代理是基于接口的
- 由于时基于接口的,因此要代理的实例的类必须实现一个接口
- 其实非常简单,就是房东需要出租房子时,去了一个中介机构,请求他们派个中介帮自己把房子租出去。然后中介机构就生成一个中介来帮他
-
案例
-
租房接口
package com.it;public interface Rent { public void rent();}
-
房东实现这个接口
package com.it;public class Host implements Rent { public void rent() { System.out.println("房东出租房子。。。"); }}
-
代理类机构定义
package com.it;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;// 使用这个类来生成代理类public class ProxyInvocationHandler implements InvocationHandler { // 要代理的接口 private Rent rent; public void setRent(Rent rent) { this.rent = rent; } // 生成得到代理类,这个代码时死的,记住就行 public Object getProxy() { return Proxy.newProxyInstance(this.getClass().getClassLoader() ,rent.getClass().getInterfaces() ,this); } // 处理要代理的人,并返回结果 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 动态代理的本质,就是使用反射机制实现 Object result = method.invoke(rent, args); return result; }}
-
测试使用
package com.it;public class Client { public static void main(String[] args) { // 真实角色 Host host = new Host(); // 代理角色,现在没有。现在时生成一个中介人机构 ProxyInvocationHandler pih = new ProxyInvocationHandler(); // 通过调用程序处理角色来处理我们要调用的接口对象 pih.setRent(host); Rent proxy = (Rent) pih.getProxy(); proxy.rent(); }}
-
输出
房东出租房子。。。
-
使用 spring api 来实现 aop
-
步骤
-
pom.xml 文件加入这个
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> </dependency> </dependencies>
-
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" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 指定要扫描的包,这样子这个包下面的注解就会生效 --> <context:component-scan base-package="com.it"/> <context:annotation-config/> <bean id="userService" class="com.it.UserServiceImpl"/> <bean id="log" class="com.it.Log"/> <bean id="afterLog" class="com.it.AfterLog"/> <!-- 使用原生 spring api 接口 --> <!-- 配置aop --> <aop:config> <!-- 切入点:express:表达似乎 --> <aop:pointcut id="pointcut"/> <!-- 执行环绕增加 --> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config></beans>
-
定义功能接口
package com.it;public interface UserService { public void add(); public void delete(); public void update(); public void select();}
-
功能接口的实现类
package com.it;public class UserServiceImpl implements UserService { @Override public void add() { System.out.println("增加了一个用户。。。"); } @Override public void delete() { System.out.println("删除了一个用户。。。"); } @Override public void update() { System.out.println("更新了一个用户。。。"); } @Override public void select() { System.out.println("查询了一个用户。。。"); }}
-
前置日志组件
package com.it;import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;public class Log implements MethodBeforeAdvice { // method : 要执行的目标对象的方法 // args : 参数 // target : 目标对象 @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName() + "的" + method.getName() + "被执行了"); }}
-
后置日志组件
package com.it;import org.springframework.aop.AfterAdvice;import org.springframework.aop.AfterReturningAdvice;import java.lang.reflect.Method;public class AfterLog implements AfterReturningAdvice { // returnValue 是返回值 @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("执行力" + method.getName() + "返回结果为:" + returnValue); }}
-
正式测试
import com.it.UserService;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); // 动态代理的是接口 UserService userService = (UserService) context.getBean("userService"); userService.add(); }}
-
输出
com.it.UserServiceImpl的add被执行了增加了一个用户。。。执行力add返回结果为:null
-
使用注解实现 aop
-
tips
- @Before
- @After
- @Arround
-
案例
-
pom.xml
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>untitled</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> </dependency> </dependencies> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties></project>
-
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" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 指定要扫描的包,这样子这个包下面的注解就会生效 --> <context:component-scan base-package="com.it"/> <context:annotation-config/> <bean id="userService" class="com.it.UserServiceImpl"/> <bean id="annoationPointCut" class="com.it.AnnoationPointCut"/> <!-- 开启 aop 注解支持 --> <aop:aspectj-autoproxy/></beans>
-
AnnoationPointCut.java
package com.it;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;// 标记这个类一个切面@Aspectpublic class AnnoationPointCut { @Before("execution(* com.it.UserServiceImpl.*(..))") public void before() { System.out.println("方法执行前。。。"); } @After("execution(* com.it.UserServiceImpl.*(..))") public void after() { System.out.println("方法执行后。。。"); }}
-
UserService.java
package com.it;public interface UserService { public void add(); public void delete(); public void update(); public void select();}
-
UserServiceImpl.java
package com.it;public class UserServiceImpl implements UserService { @Override public void add() { System.out.println("增加了一个用户。。。"); } @Override public void delete() { System.out.println("删除了一个用户。。。"); } @Override public void update() { System.out.println("更新了一个用户。。。"); } @Override public void select() { System.out.println("查询了一个用户。。。"); }}
-
测试代码
import com.it.UserService;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserService userService = (UserService) context.getBean("userService"); userService.add(); }}
-
输出
方法执行前。。。增加了一个用户。。。方法执行后。。。
-