Spring
学习:狂神
Spring
在 XML 配置的
| 属性名称 | 描述 |
|---|---|
| id | Bean 的唯一标识符,Spring IoC 容器对 Bean 的配置和管理都通过该属性完成。id 的值必须以字母开始,可以使用字母、数字、下划线等符号。 |
| name | 该属性表示 Bean 的名称,我们可以通过 name 属性为同一个 Bean 同时指定多个名称,每个名称之间用逗号或分号隔开。Spring 容器可以通过 name 属性配置和管理容器中的 Bean。 |
| class | 该属性指定了 Bean 的具体实现类,它必须是一个完整的类名,即类的全限定名。 |
| scope | 表示 Bean 的作用域,属性值可以为 singleton(单例)、prototype(原型)、request、session 和 global Session。默认值是 singleton。 |
| constructor-arg | |
| property | |
| ref | |
| value | |
| list | 用于封装 List 或数组类型的属性注入。 |
| set | 用于封装 Set 类型的属性注入。 |
| map | 用于封装 Map 类型的属性注入。 |
| entry | |
| init-method | 容器加载 Bean 时调用该方法,类似于 Servlet 中的 init() 方法 |
| destroy-method | 容器删除 Bean 时调用该方法,类似于 Servlet 中的 destroy() 方法。该方法只在 scope=singleton 时有效 |
| lazy-init | 懒加载,值为 true,容器在首次请求时才会创建 Bean 实例;值为 false,容器在启动时创建 Bean 实例。该方法只在 scope=singleton 时有效 |
| 核心 | 描述 |
|---|---|
| IOC | Inverse of Control 的简写,译为“控制反转”,指把创建对象过程交给 Spring 进行管理。 |
| AOP | Aspect Oriented Programming 的简写,译为“面向切面编程”。 AOP 用来封装多个类的公共行为,将那些与业务无关,却为业务模块所共同调用的逻辑封装起来,减少系统的重复代码,降低模块间的耦合度。另外,AOP 还解决一些系统层面上的问题,比如日志、事务、权限等。 |
所需jar包
| 名称 | 作用 |
|---|---|
| spring-core | 包含 Spring 框架基本的核心工具类,Spring 其他组件都要用到这个包中的类,是其他组件的基本核心。 |
| spring-beans | 所有应用都要用到的,它包含访问配置文件、创建和管理 Bean 以及进行 Inversion of Control(IoC)或者 Dependency Injection(DI)操作相关的所有类。 |
| spring-context | Spring 提供在基础 IoC 功能上的扩展服务,此外还提供许多企业级服务的支持,如邮件服务、任务调度、JNDI 定位、EJB 集成、远程访问、缓存以及各种视图层框架的封装等。 |
| spring-expression | 定义了 Spring 的表达式语言。 需要注意的是,在使用 Spring 开发时,除了 Spring 自带的 JAR 包以外,还需要一个第三方 JAR 包 commons.logging 处理日志信息。 |
| commons-logging |
IOC创建对象的方式
使用无参构造对象 (默认,需要Set方法)
1 | <!-- 使用Spring.来创建对象,在Spring.这些都称为Bean--> |
1 | public static void main(String[] args) { |
有参构造注入
1 | <bean id="grade" class="com.entity.Grade"> |
- 通过创建类型来注入 type (同类型容易发生错误)
1 | <bean id="grade" class="com.entity.Grade"> |
- 通过下标赋值
1 | <bean id="grade" class="com.entity.Grade"> |
注意事项:使用有参构造注入时,Java中默认构造函数的的值不为空,所以bean注入时要注意所有属性都要有值注入!Bean的自动注入时要注意!
依赖注入
- 依赖注入环境
1 | private String name; |
- Set注入
1 |
|
空间注入
p命名空间注入
- 导入xml约束
1
xmlns:p="http://www.springframework.org/schema/p"
1
2<!-- p命名空间 可以直接注入属性值 property -->
<bean id="space" class="com.entity.StuNamespace" p:name="李白" p:age="28"/>c命名空间注入 (可以无需Set方法)
1
xmlns:c="http://www.springframework.org/schema/c"
1
2<!-- c命名空间注入 通过构造器注入 constructor-arg -->
<bean id="space2" class="com.entity.StuNamespace" c:name="欧阳修" c:age="66"/>
Bean的作用域
xml配置 scope
1 | <!-- 单例模式(Spring默认机制)singleton --> |
Test代码
1 | ApplicationContext context = new ClassPathXmlApplicationContext("beans3.xml"); |
Bean的自动装配
原生xml装配
1 | <bean id="cat" class="com.entity.Cat"/> |
By Name动装配
By Type自动装配
1 | <bean id="ca1t" class="com.entity.Cat"/> |
小结:autowire
- byname 要保证所有的bean-id唯一,并且bean-id需要 和 类声明的变量(名字)一致
- by type 要保证所有的bean-class唯一,并且bean需要和自动注入的属性一致(class类型一致)
// @RequestMapping(value = “/save/{a}/{b}”,method = RequestMethod.POST) @PostMapping(“/save/{a}/{b}”) //通过请求方式 @GetMapping @DeleteMapping public String save3(@PathVariable int a, @PathVariable int b, Model model){ int res=a+b; model.addAttribute(“msg”,”save3结果为:”+res); return “hello”;}java
XML注解开发
bean
属性注入
1
2
3
4
5
6
7
8
9// 相当于:<bean id="student" class="com.ano.entity.StudentAnno"/>
// 测试类的id为当前类首字母小写的类名->studentAnno
public class StudentAnno {
// public String name="欧阳修";
//<property name="name" value="李太白"/>
public String name;
}1
2
3
4<!-- 开启事务扫描 -->
<context:component-scan base-package="com.ano.entity"/>
<!-- 开启注解支持 -->
<context:annotation-config/>衍生注解
- @Component 的衍生注解,通常在web开发中,在mvc架构使用 ,功能于原生注解一样
- dao [@Repository]
- service [@Service]
- controller [@Controller]
- @Component 的衍生注解,通常在web开发中,在mvc架构使用 ,功能于原生注解一样
自动装配
- @Autowired
- @Qualifier
- @Resource
作用域 @Scope
1
2
3
4
5
6
7
8
public class StudentAnno {
// public String name="欧阳修";
//<property name="name" value="李太白"/>
public String name;
}
| 序号 | 注解 & 描述 |
|---|---|
| 1 | @Required 注解应用于 bean 属性的 setter 方法。 |
| 2 | @Autowired 注解可以应用到 bean 属性的 setter 方法,非 setter 方法,构造函数和属性。 |
| 3 | @Qualifier通过指定确切的将被连线的 bean, @Autowired 和 @Qualifier 注解可以用来删除混乱。 |
| 4 | JSR-250 Annotations Spring 支持 JSR-250 的基础的注解,其中包括了 @Resource,@PostConstruct 和 @PreDestroy 注解。 |
注解实现自动装配
注意,除了 spring 的四个基础 jar 包和 commons-logging-xxx.jar 外,想要使用注解实现 Spring 自动装配,还需要引入Spring 提供的 spring-aop 的 Jar 包。
导入约束
1
2
3
4
5
6
7
8
9
10
11
12
13
<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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启注解支持 -->
<context:annotation-config/>
</beans>配置注解支持
1
2<!-- 开启注解支持 -->
<context:annotation-config/>@Autowired
- 直接在属性上使用即可,也可以在Set方式上使用!(反射实现)
- 使用Autowired我们可以不用编写Set方法了,前提是你这个自动装配的属性在IOC(Spring)容器中存在,且符
合byname! - @Autowired 注解应用于setter,属性,构造函数,字段…..
@Nullable
- 允许字段为null
@Qualifier
- 如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候、我们可以
使用@Qualifier(value=”id”)去配置@Autowired的使用,指定一个唯一的bean对象注入!
- 如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候、我们可以
测试代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14public class People {
//如果显示定义了Autowired,的required,属性为False,说明这个对象可以nuLL,否则不允许为
//只能通过cat222注入属性
private Cat cat;
private Dog dog;
private String name;
public People( String name) {
}
}1
2
3
4
5
6
7<bean id="cat111" class="com.entity.Cat"/>
<bean id="dog111" class="com.entity.Dog"/>
<bean id="cat222" class="com.entity.Cat"/>
<bean id="dog222" class="com.entity.Dog"/>
<bean id="people" class="com.entity.People"/>@Resource
1
2
3
4
5
6
7public class People {
private Cat cat;
//只能匹配dog111
private Dog dog;
private String name;
}1
2
3
4
5
6<bean id="cat111" class="com.entity.Cat"/>
<bean id="dog111" class="com.entity.Dog"/>
<bean id="dog222" class="com.entity.Dog"/>
<bean id="people" class="com.entity.People"/>jdk1.8之外的版本需要导入jar包才能使用@Resource
1
2
3
4
5<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
小结:
@Resource和@Autowired的区别:
- 都是用来自动装配的,都可以放在属性字段上
- @Autowired通过byType的方式实现,而且必须要求这个对象存在!【常用】
- @Resource默认通过byname的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就报错!【常用】
- @Resource在高版本的jdk中需要导入jar包,(不过在我的jdk17.2中只需开启注解支持就会自动装配)
Java注解开发
Java Config
实体类注册
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17//这里这个注解的意思,就是说这个类spring接管了,注册到了容器中
public class User {
private String name;
private Cat cat;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}使用java配置替代bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21//这个也会Spring容器托管,注册到容器中,因为他本米就是一个@Component
//@Configuration代表这是一个配置类,就和我们之前看的beans.xml
public class BeanConfig {
//注册一个bean,就相当于我们之前写的一个bean标签
//这个方法的名字,就相当于bean标签中的id属性
//这个方法的返回值,就相当于bean标签中的cLass属性
//@Bean(name = "XXX") 可以自定义beanid
//直接使用@Bean,beanid为getUsser
public User getUser() {
return new User();
}
public Cat getCat(){
return new Cat();
}
}测试类
1
2
3
4
5
6
7
8
9
10public class Testconfig {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
//bean获取的属性由java配置类中返回
User bean = (User) context.getBean("getUser");
System.out.println(bean.getName());
}
}
Spring-AOP
| 术语 | 描述 |
|---|---|
方面/切面(Aspect) | 一个具有一组API的模块,提供交叉要求。例如,日志记录模块被称为AOP方面用于记录。应用程序可以根据需要具有任意数量的方面。 |
加入点(Join point) | 这表示您的应用程序中可以插入AOP方面的一点。也可以说,这是应用程序中使用Spring AOP框架采取操作的实际位置。 |
通知(Advice) | 这是在方法执行之前或之后采取的实际操作。 这是在Spring AOP框架的程序执行期间调用的实际代码片段。 |
切入点(Pointcut) | 这是一组一个或多个连接点,其中应该执行通知(Advice)。 您可以使用表达式或模式指定切入点,我们将在AOP示例中看到。 |
介绍(Introduction) | 介绍允许向现有类添加新的方法或属性。 |
目标对象(Target object) | 对象被一个或多个方面通知(Advice),该对象将始终是代理的对象。也称为通知(Advice)对象。 |
编织(Weaving) | 编织是将方面与其他应用程序类型或对象进行链接以创建通知(Advice)对象的过程。 这可以在编译时,加载时间或运行时完成。 |
Spring AOP中可以使用以下五种建议:
| 通知 | 描述 |
|---|---|
before | 在方法执行之前运行通知。 |
after | 在方法执行后运行通知,无论其结果如何。 |
after-returning | 只有方法成功完成后才能在方法执行后运行通知。 |
after-throwing | 只有在方法通过抛出异常而退出方法执行之后才能运行通知。 |
around | 在调用通知方法之前和之后运行通知。 |
导包
1 aop,aspectjweaver
AOP实现方式一
实现相应的类接口
MethodBeforeAdvice
1
2
3
4
5
6
7
8
9
10public class Log implements MethodBeforeAdvice {
//method:要执行的日标对象的方法
//args:参数
//target:目标对象
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName() +"执行了\t"+method.getName());
// System.out.println(method+"\n"+args+"\n"+target);
}
}AfterReturningAdvice
1
2
3
4
5
6public class AfterLog implements AfterReturningAdvice {
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName() +"执行了\t"+method.getName());
}
}1
2
3
4
5
6
7
8
9
10
11
12
13<bean id="userServiceImpl" class="com.service.UserServiceImpl"/> //自定义的接口实现类(被切)
<bean id="log" class="com.log.Log"/> //
<bean id="afterLog" class="com.log.AfterLog"/> //
<!-- 配置aop:导入约束-->
<aop:config>
<!-- 切入点:expression:表达式execution(要执行的位置***)-->
<aop:pointcut id="pointcut" expression="execution(* com.service.UserServiceImpl.*(..))"/>
<!-- 执行环绕增加-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/> //把log类切入到pointcut方法内
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>1
2
3
4
5
6
7
public void test1(){
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
//动态代理实现的是接口
UserService service = context.getBean("service", UserService.class);
service.add();
}execution
1
2
3execution([访问修饰符] 返回值 包名.类/接口.方法名(参数)异常名)
execution( int com.service.UserImpl.findById(int) )AOP实现方式二
切面
1
2
3
4
5
6
7
8public class DiyPointCut {
public void before(){
System.out.println("===============方法执行前============");
}
public void after(){
System.out.println("===============方法执行后============");
}
}1
2
3
4
5
6
7
8<bean id="diy" class="com.diy.DiyPointCut"/>
<aop:config>
<aop:aspect ref="diy">
<aop:pointcut id="pointcut" expression="execution(* com.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>注解实现AOP
注意还需要导入相应的约束
1
2
3
4
5
6
7
8
9
10
11
12
13
public class AnnotationPointCut {
public void before(){
System.out.println("===============方法执行前(注解--—)============");
}
public void after(){
System.out.println("===============方法执行后(注解—)============");
}
}1
2
3
4
5<context:component-scan base-package="com.diy"/>
<context:annotation-config />
<!-- <bean id="anno" class="com.diy.AnnotationPointCut"/>-->
<aop:aspectj-autoproxy/>
Spring-DataSource
手动创建数据源
导jar包。mysql-connector-java,c3p0,druid
1 | //测试手动创建c3p0数据源 |
1 | //测试手动创建druid数据源(使用properties配置文件) |
spring创建数据源
1 | //注册配置文件 |
1 |
|
Spring-Mybatis
入门
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34// 导jar包
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> //mysql数据库连接
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId> //mybatis
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId> //springmvc
<version>5.3.19</version>
</dependency>
<!-- 连接spring操作数据库-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId> //spring-JDBC
<version>5.3.19</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId> //mybatis-spring
<version>2.0.7</version>
</dependency>
</dependencies>dataSource:使用spring数据源替换mybatis配置
1
2
3
4
5
6<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?serverTimezone=GMT%2B8&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="000000"/>
</bean>bean注册sqlSessionFactory工厂
1
2
3
4
5
6
7<!-- sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 绑定mybatis配置文件(此处绑定就不需要在mybatis配置中写了) -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- <property name="mapperLocations" value="classpath:com/dao/UserMapper.xml"/>-->
</bean>实现实体类映射接口–SqlSessionTemplate
1
2
3
4
5
6
7
8
9
10
11
12
13
14public class UserMapperImpl implements UserMapper{
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
public List<User> findAll() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.findAll();
}
}注册SqlSessionTemplate
1
2
3<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>注册实体类映射实现类
1
2
3<bean id="userMapper" class="com.dao.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"/>
</bean>实现实体类映射接口方式2
实现实体类映射接口–SqlSessionDaoSupport
1
2
3
4
5
6
7
8
9
10
11
12public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
@Override
public List<User> findAll() {
// SqlSession sqlSession=getSqlSession();
// UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// return mapper.findAll();
return getSqlSession().getMapper(UserMapper.class).findAll();
}
}注册实体类映射实现类
1
2
3
4
5<!-- 直接注入sqlSessionFactory,无需在注册 SqlSessionTemplate(session) -->
<bean id="userMapper" class="com.mapper.UserMapperImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>






