Spring
核心思想Ioc
- 控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中。
- 控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
Spring程序开发步骤
- 导入 Spring 开发的基本包坐标
- 编写 Dao 接口和实现类
- 创建 Spring 核心配置文件
- 在 Spring 配置文件中配置 UserDaoImpl
- 使用 Spring 的 API 获得 Bean 实例
思考
-
对象是谁创建的 ? 对象是由Spring创建的
-
对象的属性是怎么设置的 ? 对象的属性是由Spring容器设置的
-
控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的。
-
反转 : 程序本身不创建对象 , 而变成被动的接收对象 .
-
依赖注入 : 就是利用set方法来进行注入的.
-
IOC是一种编程思想,由主动的编程变成被动的接收
注解开发
- 使用注解进行开发时,需要在applicationContext.xml中配置组件扫描,作用是指定哪个包及其子包下的Bean需要进行扫描以便识别使用注解配置的类、字段和方法。
@Component 使用在类上用于实例化Bean
@Controller 使用在web层类上用于实例化Bean
@Service 使用在service层类上用于实例化Bean
@Repository 使用在dao层类上用于实例化Bean
@Autowired 使用在字段上用于根据类型依赖注入
@Qualifier 结合@Autowired一起使用用于根据名称进行依赖注入
@Resource 相当于@Autowired+@Qualifier,按照名称进行注入
@Value 注入普通属性
@Scope 标注Bean的作用范围
Spring集成web环境
分析
- 应用上下文对象是通过new ClasspathXmlApplicationContext(spring配置文件) 方式获取的,但是每次从容器中获得Bean时都要编写new ClasspathXmlApplicationContext(spring配置文件) ,这样的弊端是配置文件加载多次,应用上下文对象创建多次。
- 在Web项目中,可以使用ServletContextListener监听Web应用的启动,我们可以在Web应用启动时,就加载Spring的配置文件,创建应用上下文对象ApplicationContext,在将其存储到最大的域servletContext域中,这样就可以在任意位置从域中获得应用上下ApplicationContext对象了。
实现
上面的分析不用手动实现,Spring提供了一个监听器ContextLoaderListener就是对上述功能的封装,该监听器内部加载Spring配置文件,创建应用上下文对象,并存储到ServletContext域中,提供了一个客户端工具WebApplicationContextUtils供使用者获得应用上下文对象。
步骤
- 在web.xml中配置ContextLoaderListener监听器(导入spring-web坐标)
- 使用WebApplicationContextUtils获得应用上下文对象ApplicationContext
代码
1<!--全局参数-->
2<context-param>
3 <param-name>contextConfigLocation</param-name>
4 <param-value>classpath:applicationContext.xml</param-value>
5</context-param>
6<!--Spring的监听器-->
7<listener>
8 <listener-class>
9 org.springframework.web.context.ContextLoaderListener
10 </listener-class>
11</listener>
静态代理
优点
- 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情。
- 公共的业务由代理来完成 ,实现了业务的分工 ,
- 公共业务发生扩展时变得更加集中和方便
缺点
- 类多了,多了代理类 , 工作量变大了 . 开发效率降低 。
- 我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理 !
思想
我们在不改变原来的代码的情况下,实现了对原有功能的增强,这是AOP中最核心的思想。
动态代理
概述
- 动态代理的角色和静态代理的一样
- 动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
- 动态代理分为两类 :
- 一类是基于接口动态代理 ,
- 一类是基于类的动态代理
- 基于接口的动态代理----JDK动态代理
- 基于类的动态代理--cglib
JDK动态代理
核心 : InvocationHandler和Proxy
- InvocationHandler是由代理实例的调用处理程序实现的接口。 只有一个方法。
- 每个代理实例都有一个关联的调用处理程序。
- 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。
示例代码
1//这个类是用来动态生成代理类的,它不是代理类
2public class ProxyInvocationHandler implements InvocationHandler {
3 //被代理的接口
4 private UserService userService;
5
6 public void setUserService(UserService userService) {
7 this.userService = userService;
8 }
9
10 //得到代理类
11 public Object getProxy(){
12 return Proxy.newProxyInstance(this.getClass().getClassLoader(),userService.getClass().getInterfaces(),this);
13 }
14
15 @Override
16 //处理代理实例,并且返回结果
17 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
18 //动态代理的实质,就是用反射机制来实现的。
19 Object result = method.invoke(userService, args);
20 return result;
21 }
22}
AOP
概念
- AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
AOP的作用
提供声明式事务;允许用户自定义切面
即 Aop 在 不改变原有代码的情况下 , 去增加新的功能 (方法增强)
Spring实现AOP
1.使用AOP织入,需要导入一个依赖包!
1<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
2<dependency>
3 <groupId>org.aspectj</groupId>
4 <artifactId>aspectjweaver</artifactId>
5 <version>1.9.4</version>
6</dependency>
- 编写自己的业务类
- 然后去写我们的增强类 , 我们编写两个 , 一个前置增强 一个后置增强
1public class BeforeLog implements MethodBeforeAdvice {
2
3 /**
4 *
5 * @param method 要执行的目标对象的方法
6 * @param args 目标对象的方法的参数
7 * @param target 目标对象
8 * @throws Throwable
9 */
10 public void before(Method method, Object[] args, Object target) throws Throwable {
11 System.out.println(target.getClass().getName()+"准备执行"+method.getName()+"方法");
12 }
13}
后置增强
1public class AfterLog implements AfterReturningAdvice {
2 /**
3 *
4 * @param returnValue 目标对象的方法的返回值
5 * @param method 目标对象的方法
6 * @param args 目标对象的方法的参数
7 * @param target 目标对象
8 * @throws Throwable
9 */
10 public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
11 System.out.println(target.getClass().getName()+"执行了"+method.getName()+"方法,返回值是:"+returnValue);
12 }
13}
在spring中声明AOP
1<!-- 注册bean对象-->
2 <bean id="userService" class="com.Gao.Service.UserServiceImpl"/>
3 <bean id="beforeLog" class="com.Gao.Log.BeforeLog" />
4 <bean id="afterLog" class="com.Gao.Log.AfterLog" />
5
6<!-- 配置AOP-->
7 <aop:config>
8<!-- 配置切入点 expression:表达式 * * * * * 对应(修饰词 返回值 列名 方法名 参数) -->
9 <aop:pointcut id="pointcut" expression="execution(* com.Gao.Service.UserServiceImpl.*(..))"/>
10<!--执行环绕增强-->
11 <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
12 <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut" />
13 </aop:config>