文章目录
Day40 Spring注解&代理模式&AOP
Spirng注解
什么是Spring
Spring是一款轻量级的DI/IOC和AOP容器
Spring就是javabean的一个容器
Spring的两大核心
- DI/IOC
- IOC:控制反转 把当前应用对象中bean的创建权利都交给spring来管理 这种创建对象权利的反转就叫做控制反转
- DI:依赖注入 我们把spring创建的bean 注入到指定接口的过程 这种方式就叫做依赖注入
- AOP
- 面向切面编程
编程思想
- 面向对象:强调的是一个封装性 模块化 更加符合人们的思想
- 面向过程:是C语言强调的一种编程思想
- 面向接口:其实就是指的在controller层注入service或service层中注入dao 定义的字段都应该是接口 定义接口的好处就是能够进行有效的解耦 扩展性更强一点 维护性更好
- 面向切面:它的作用其实就是对公共业务逻辑代码进行抽取 让代码进行解耦 让代码的扩展性更加强一点
- 面向百度:当掌握了基础知识以后 如果遇到做不来的功能 不可能一直看着 应该想尽一切办法进行解决 而在真实开发中 程序员都是面向百度 必应 google编程的
依赖注入
普通注入
<bean id="myBean" class="cn.itsource._01di.MyBean">
<!--
构造器注入,方案1:通过索引注入
<constructor-arg index="0" value="122"/>
<constructor-arg index="1" value="王天霸"/>
方案3:通过构造器参数类型注入 最不推荐
<constructor-arg type="java.lang.Long" value="22"/>
<constructor-arg type="java.lang.String" value="西门吹雪"/>
方案4: 通过构造器参数顺序注入 不推荐
<constructor-arg value="33"/>
<constructor-arg value="阮惊天"/>
-->
<!--方案2:通过构造器名字注入 最推荐使用-->
<constructor-arg name="id" value="111"/>
<constructor-arg name="name" value="李很弱"/>
<!--
属性注入
value:给基本属性设置值
ref: 只能用于对象,给对象设置值
-->
<property name="sex" value="true"/>
<property name="salary" value="4000"/>
<!--
方案1:给对象注入值
<property name="otherBean" ref="otherBean1"/>
-->
<!--方案2:给对象注入值-->
<property name="otherBean">
<bean class="cn.itsource._01di.OtherBean">
<constructor-arg name="id" value="1"/>
<constructor-arg name="name" value="洪熙官"/>
</bean>
</property>
<!--给普通list注入值,元素非对象-->
<property name="list">
<list>
<value>苗翠花</value>
<value>方德</value>
<value>雷老虎</value>
</list>
</property>
<!--给普通list注入值,元素是对象-->
<property name="otherBeanList">
<list>
<bean class="cn.itsource._01di.OtherBean">
<constructor-arg name="id" value="2"/>
<constructor-arg name="name" value="楚楚"/>
</bean>
<bean class="cn.itsource._01di.OtherBean">
<constructor-arg name="id" value="3"/>
<constructor-arg name="name" value="步惊云"/>
</bean>
<ref bean="otherBean1"/>
</list>
</property>
<property name="set">
<set>
<value>4</value>
<value>6</value>
<value>5</value>
<value>2</value>
<value>3</value>
<value>4</value>
</set>
</property>
<property name="otherBeanSet">
<set>
<ref bean="otherBean1"/>
<ref bean="otherBean1"/>
<bean class="cn.itsource._01di.OtherBean">
<constructor-arg name="id" value="12"/>
<constructor-arg name="name" value="聂风"/>
</bean>
</set>
</property>
<!--
properties的注入
标准用法,推荐使用
-->
<property name="props1">
<props>
<prop key="jdbc.username">root</prop>
<prop key="jdbc.password">123456</prop>
<prop key="jdbc.driverClassName">com.mysql.jdbc.Driver</prop>
<prop key="jdbc.url">jdbc:mysql:///crud</prop>
<prop key="jdbc.autor">老孙</prop>
</props>
</property>
<!--properties简写方式,不支持中文-->
<property name="props2">
<value>
k1=v1
k2=v2
k3=v3
k4=测试一把
</value>
</property>
<!-- 数组标准注入
<property name="arrays">
<array>
<value>How</value>
<value>Are</value>
<value>You</value>
</array>
</property>
-->
<!--简写方式-->
<property name="arrays" value="SUN,FU,Lin"/>
</bean>
<bean id="otherBean1" class="cn.itsource._01di.OtherBean">
<constructor-arg name="id" value="11"/>
<constructor-arg name="name" value="金莲"/>
</bean>
</beans>
XML方式自动注入
- default-autowire=“byName” 根据名字自动注入 按照属性的名称 setXxx方法
- default-autowire=“byType” 根据类型注入按照注入对象的类型,要求:类型只能配置一个实例
- default-autowire=“constructor” 根据构造器注入
默认是类型注入
当你在指定的bean中告诉我们使用名字注入,类型注入就被覆盖了
<bean id="userService" class="cn.itsource._02xml_auto_di.service.impl.UserServiceImpl" autowire="byName" >
全注解注入
<context:component-scan base-package="cn.itsource._03all_auto_di"/>
开启组件扫描器 可以扫描到
- @Controller 控制层
- @Service 业务层
- @Repository 持久层
- @Component 非以上三层结构就贴此接口
以上四个注解源码都是一模一样的,都表示该类交给spring管理,它们仅仅代表一种标志而已
意思就是,如果你的类贴上了@Controller,就证明你这个类是属于控制层的
- @Autowired 自动注入 特点:先根据类型注入,类型匹配不到,再根据名字注入
@Repository加了此注解意思就是
<bean id="userDaoJPAImpl" class="cn.itsource._03all_auto_di.dao.impl.UserDaoJPAImpl"/>
@Repository(“userDao”)
<bean id="userDao" class="cn.itsource._03all_auto_di.dao.impl.UserDaoJPAImpl"/>
@Autowired 与 @Resource的区别
- @Autowired与@Resource都是依赖注入字段
- @Autowired它是spring提供的注解
- @Resource它是sun公司提供的注解
- @Autowired它是先根据类型匹配,类型匹配不到则根据名字匹配
- @Resource它是先根据名字匹配,名字匹配不到则根据类型匹配
以后注入对象的时候,推荐使用@Autowired 因为它和spring进行无缝集成
@Qualifier(“userDaoJPAImpl”) 查找名字为userDaoJPAImpl的bean注入到我这个接口中
@Resource(name = “userDaoJPAImpl”)
AOP
AOP底层是基于代理模式实现的
代理模式
分类
- 静态代理
- 动态代理
- JDK动态代理 他只能代理有接口的实现类
- CGLIB动态代理 他既能代理有接口的实现类 也能代理没有没有接口的类
AOP术语(了解)
- 连接点(Joinpoint):程序执行的某一个特定位置,如类初始前后,方法的运行前后。而Spring只支持方法的连接点
- 切点(Pointcut):切点可以定位到相应的连接点,一个切点可以定位多个连接点。
- 增强(Advice):又被称为通知,完成逻辑的增强。
- 目标对象(Target):增强逻辑织入的目标类。
- 引介(Introduction):特殊的增强,为类添加一些属性和方法。
- 织入(Weaving): 将增强添加到目标类的具体连接点上的过程。Spring使用动态代理织入。
- 代理(Proxy):一个类(原类)被织入增强(逻辑)后,就产生一个结果类,称为代理类。
- 使用AOP完成所有的功能都是通过代理类来完成的
- 切面(Aspect):由切点和增强组成
配置
配置的时候一定要记住三个要素:何时,何地,做什么事
何时:在执行方法之前/之后/有异常…
何地:在哪些包中的哪些类的哪些方法上面执行
做什么事: 在UserServie中执行update方法之前添加日志
静态代理
静态代理的缺陷:
一个接口需要一个代理类
5个接口就需要5个代理类,太过于麻烦了,维护成本太高了
就相当于真实开发: 1个中介 只能代理1个房东 这是不合理的
正确合理的场景: 1个中介可以代理n个房东
AOP的配置
定义切点
- cn.itsource._06aop_xml.service.IService.(…) 我要在cn.itsource._06aop_xml.service包下面所有以I开始并且Service结尾的类或者接口中所有的方法切上一刀
第一个*: 任意返回值类型
第二个*:I开头的Service结尾的类
第三个*:类中的任意方法 (可变参数)
一般执行方法
<!--前置通知
<aop:before method="begin" pointcut-ref="pointcut"/>-->
<!--后置通知
<aop:after method="commit" pointcut-ref="pointcut"/>-->
<!--异常通知
<aop:after-throwing method="rollback" pointcut-ref="pointcut"/>-->
<!--最终通知
<aop:after-returning method="close" pointcut-ref="pointcut"/>-->
注意:当默认执行的顺序不是我们想要的,所以我们一般使用环绕通知,环绕通知就是自己去写业务逻辑
<aop:around method="around" pointcut-ref="pointcut"/>
aop的配置
<aop:config>
<!--
定义切点
*cn.itsource._06aop_xml.service.I*Service.*(..) 我要在cn.itsource._06aop_xml.service包下面所有以I开始并且Service结尾的类或者接口中所有的方法切上一刀
第一个*: 任意返回值类型
-->
<aop:pointcut id="pointcut" expression="execution(* cn.itsource._06aop_xml.service.I*Service.*(..))"/>
<aop:aspect ref="txManager">
<!--前置通知
<aop:before method="begin" pointcut-ref="pointcut"/>-->
<!--后置通知
<aop:after method="commit" pointcut-ref="pointcut"/>-->
<!--异常通知
<aop:after-throwing method="rollback" pointcut-ref="pointcut"/>-->
<!--最终通知
<aop:after-returning method="close" pointcut-ref="pointcut"/>-->
<!-- 注意:当默认执行的顺序不是我们想要的,所以我们一般使用环绕通知,环绕通知就是自己去写业务逻辑-->
<!--环绕通知-->
<aop:around method="around" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>