Spring轻量级开发框架(一)https://developer.aliyun.com/article/1469575
7.3、使用注解实现自动装配
jdk1.5支持的注解,Spring2.5就支持注解了
要使用注解须知:
- 导入约束: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:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/beans/spring-context.xsd "> </beans>
@Autowired
直接在属性上使用即可,也可以在set方法上使用
使用Autowired我们可以不用编写Set方法,前提是自动装配的属性在IOC容器中存在,且命名符合byname!
科普:
@NULLABLE 字段标记了这个字段,说明这个字段可以为null
public @interface Autowired { boolean required() default true; }
//如果显式的定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空
@Qualifier(value ="dog")//自动装配指定id名字
如果@Autowired
自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired
】完成的时候,我们可以使用@Qualifier(value ="xxx")去配置
@Autowired
的使用,指定一个唯一的bean对象注入
//如果显式的定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空 @Autowired private cat cat; @Autowired @Qualifier(value ="dog") private Dog dog;
@Resource注解
@Resource(name = "cat") private cat cat;
小结:
@Resoure和@Autowired的区别:
- 都是用来自动装配的,都可以放在属性字段上
- @Auowired通过ByType的方式实现,而且必须有要求的对象存在【常用】
- @Resource默认通过byname的方式实现,如果找不到名字,则通过byType实现,如果两个都找不到,就报错!【常用】
- 执行先后顺序不同:@Auowired通过ByType的方式实现,@Resource默认通过byname的方式实现
8、使用注解开发
在Spring4之后,要使用注解开发必须要保证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:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/beans/spring-context.xsd "> </beans>
- bean
@Component(value = "user")//相当于注册bean,放在类上相当于类被Spring管理
- 属性如何注入
@Value("胡宇辰")相当于 <property name="name" value="胡宇辰"></property>
- 衍生的注解
- @Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层
- dao-->[@Repository]
- service-->[@Service]
- controller-->[@Controller]
这四个注解功能都是一样的,都是代表将某个类注册到Spring中装配bean
- 自动装配
- @Auowired通过ByType的方式实现,而且必须有要求的对象存在【常用】 - @Resource默认通过byname的方式实现,如果找不到名字,则通过byType实现,如果两个都找不到,就报错!【常用】 -@Component(value = "user")//相当于注册bean,放在类上相当于类被Spring管理
- 作用域
@Scope(scopeName = "singleton")
- 小结
xml与注解
- xml更加万能,适用于任何场合!维护简单方便
- 注解不是自己的类使用不了,维护相对复杂
xml与注解的最佳时间
- xml用来管理所有的bean
- 注解负责属性的注入
- 在我们使用的过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持
<context:component-scan base-package="com.hyc"></context:component-scan> <context:annotation-config></context:annotation-config>
9、使用java的方式配置Spring
我们现在要完全不使用Spring的xml配置了,全权交给java来做!
javaConfig是Spring的一个子项目,他是在Spring4之后变成了核心功能
配置类
package com.hyc.HycConfig; import com.hyc.pojo.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration//这个也会被Spring容器托管,被注册到容器中,应为本来他就是一个Component,@Configuration代表这是一个配置类,和我们之前的beans。xml是一样的 @ComponentScan("com.hyc") @Import(HycConfigto02.class) public class HycConfigto { //注册一个bean,就相当于是我们之前写的一个bean标签 //这个方法的名字就是bean标签中的id属性 //这个方法的返回值就相当于,bean标签的class @Bean public User Getuser(){ return new User(); } }
实体类
package com.hyc.pojo; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; //这里这个注解的意思是这个类被Spring接管了,注册到了容器中 @Component public class User { private String name; @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } public String getName() { return name; } @Value("hyc") public void setName(String name) { this.name = name; } }
测试类
import com.hyc.HycConfig.HycConfigto; import com.hyc.pojo.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MyTest { @Test public void show(){ //如果完全使用了配置类方式去做,我们就只能通过ApplicationContext上下文来获取容器,通过配置类的class对象加载! ApplicationContext context = new AnnotationConfigApplicationContext(HycConfigto.class); User user = (User) context.getBean("Getuser"); System.out.println(user.getName()); } }
这种纯java配置,在SpringBoot随处可见
10、代理模式
中介: 为什么学习代理模式,应为这就是SpringAOP的底层,
面向切面编程的底层实现!【SpringAOP和SpringMVC】
代理模式分类
- 静态代理
- 动态代理
10.1、静态代理
角色分析:
- 抽象角色:一般会使用接口或者抽象类来解决
- 真实角色:被代理的角色,
- 代理角色:代理真实角色后,会做一些附属操作
- 客户:访问代理对象的人!
代理步骤:
- 接口
package com.hyc.demo01; public interface Rent { public void rent(); }
- 真实角色
package com.hyc.demo01; public class Host implements Rent { public void rent() { System.out.println("房东要出租房子"); } }
- 代理角色
package com.hyc.demo01; public class Proxy implements Rent{ private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } public void rent() { seeHourse(); host.rent(); hetong(); Fare(); } public void seeHourse(){ System.out.println("中介带你看房"); } public void Fare(){ System.out.println("收中介费"); } public void hetong(){ System.out.println("签租赁合同"); } }
- 客户端访问
package com.hyc.demo01; public class Client { public static void main(String[] args) { // //房东要租房子,不想自己干活 Host host = new Host(); //中介帮房东租房子,代理角色一般会有一些附属操作 Proxy proxy = new Proxy(host); //你不用面对房租,直接找总中介租房就可以了 proxy.rent(); } }
代理模式好处:
- 可以让真实角色的操作更加纯粹,不用去关注一些公共的业务
- 公共业务交给代理角色,实现了分工
- 公共业务发生拓展的时候,方便集中管理
缺点:
- 一个真实觉得就会产生一个代理角色,代码量会翻倍,开发效率会变低
10.2、加深理解
代码对应:demo02
AOP记录
10.3、动态代理
如何改变静态代理的缺点
- 动态代理和静态代理的角色一样
- 动态代理的代理类是动态生成的,不是我们写好的
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 最经典的基于接口:JDK的动态代理【我们使用这一种】
- 基于类的:cglib
- java字节码实现:javassist
需要了解两个类:Proxy,InvocationHandler
动态代理的好处:
- 可以让真实角色的操作更加纯粹,不用去关注一些公共的业务
- 公共业务交给代理角色,实现了分工
- 公共业务发生拓展的时候,方便集中管理
- 一个动态代理类代理的是一个接口,一般就是对应的一类业务
11、AOP
11.1 什么是AOP
AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
11.2 Aop在Spring中的作用
提供声明式事务;允许用户自定义切面
- 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 ….
- 切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。
- 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
- 目标(Target):被通知对象。
- 代理(Proxy):向目标对象应用通知之后创建的对象。
- 切入点(PointCut):切面通知 执行的 “地点”的定义。
- 连接点(JointPoint):与切入点匹配的执行点。
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:
即 Aop 在 不改变原有代码的情况下 , 去增加新的功能 .
11.3 使用Spring实现Aop
【重点】使用AOP织入,需要导入一个依赖包!
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --><dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version></dependency>
实现方式一:
使用SpringAPI接口实现AOP【SpringAPI接口实现】
实现方式二:
自定义来实现AOP【主要是切面】
实现方式三:
使用注解实现
12、整合Mybatis
整合步骤:
- 导入相关jar包
- 编写配置文件
- 测试
12.1、回忆Mybatis
- 编写实体类
- 编写核心配置文件
- 编写接口
- 编写Mapperx.xml
- 测试
12.2、Mybatis-spring
第一种方法:传统xml的配制方法
- 编写数据源配置
<!--数据源--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean>
- sqlSessionFactory
<!--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/hyc/Mapper/UserMapper.xml"/> </bean>
- sqlSessionTemplate
<!--SqlSessionTemplate就是我们使用的sqlSeesion--> <bean id="sqlsession" class="org.mybatis.spring.SqlSessionTemplate"> <!-- 只能使用构造器注入,因为它没有set方法--> <constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg> </bean>
- 需要给接口加实现类
public class UserMapperImpl implements UserMapper { //在原来,我们所有的sqlsession来执行,现在我们使用Spring中sqlSessionTemplate private SqlSessionTemplate sqlSession; public void setSqlSession(SqlSessionTemplate sqlSession) { this.sqlSession = sqlSession; } public List<User> selectUser() { UserMapper mapper = sqlSession.getMapper(UserMapper.class); return mapper.selectUser(); } }
- 将自己写的实现类,注入到Spring中
<bean id="UserMapperClass" class="com.hyc.Mapper.UserMapperImpl"> <property name="sqlSession" ref="sqlsession"/> </bean>
- 测试使用即可
@Test public void test() throws IOException { ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); UserMapper userMapperClass = (UserMapper) context.getBean("UserMapperTwo"); List<User> userList = userMapperClass.selectUser(); for (User user : userList) { // System.out.println(user); }
第二种方法:使用新特性SqlSessionDaoSupport
- 绑定数据源
<!--数据源--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean>
- sqlSessionFactory
<!--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/hyc/Mapper/UserMapper.xml"/> </bean>
- 编写继承SqlSessionDaoSupport的类
public class UserMapperTwo extends SqlSessionDaoSupport implements UserMapper { public List<User> selectUser() { return getSqlSession().getMapper(UserMapper.class).selectUser(); } }
- 去spring中装配SqlSessionDaoSupport支持类注入sqlSessionFactory
<bean id="UserMapperTwo" class="com.hyc.Mapper.UserMapperTwo"> <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> </bean>
- 测试
public class MyTest { @Test public void test() throws IOException { ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); UserMapper userMapperClass = (UserMapper) context.getBean("UserMapperTwo"); List<User> userList = userMapperClass.selectUser(); for (User user : userList) { // System.out.println(user); } } }
Spring轻量级开发框架(三)https://developer.aliyun.com/article/1469577