Spring的IOC注解开发与AOP
一 IOC实现的注解形式
1SpringAOP的常用注解
官方建议使用这三个衍生注解,层次清晰,针对每一层
@Controller web层
@Service service层
@Responsitory dao层
@Autowired 注入对象,按类型注入。我们一般都是按照名称来注入,加一个Qualifier注解,必须让@Autowired和@Qualifier一起来使用,来完成按照名称的属性注入,
一般属性用value,对象属性用Resource
代码实现:
(1)编写UserDao的接口
package com.itheima.demo1; public interface UserDao { public void save(); }
(2)ApplicationContext.xml配置
(3)编写UserDao的实现类
package com.itheima.demo1; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Repository; //标记数据访问组件,即UserDao @Repository("UserDao") public class UserDaoImpl implements UserDao { @Value("花花") private String name; @Override public void save() { System.out.println("UseDao的save方法执行了"+" 姓名是"+name); } }
(4)测试类
public class TestDemo1 { /** * 使用注解的方式实现 * demo1使用的是UserDao */ @Test public void demo1(){ ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao= (UserDao) applicationContext.getBean("UserDao"); userDao.save(); } }
运行成功的结果图:
2 Bean作用的作用范围的注解(重点):
@scope
singleton:单例
prototype:多例
3 Bean的声明周期的注解
初始化的注解:PostCostrucct
销毁的注解:PerDestroy
代码片段
4XML和注解的比较
XML:适合任何场景 特点:结构清晰,方便维护
注解:有些地方用不了(这个类不是自己提供的) 特点:开发方便
XML和注解整合开发(各取所长),XML管理Bean、注解属性注入
二 AOP的开发
1 什么是AOP?
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程。AOP是OOP的扩展、延申,解决oop开发遇到的问题。
利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
2 AOP采用的是横向抽取机制(代理机制)取代了传统的纵向继承.
Spring底层的AOP实现原理是动态代理
jdk的动态代理:只能对实现接口的类实现动态代理
Cglib动态代理(类似于Javassist第三方的动态代理)
3 jdk的动态代理部分代码实现
jdkProxy类
package com.baidu.demo; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class JdkProxy implements InvocationHandler { private UserService userService; //把增强的对象传到proxy中 public JdkProxy(UserService userService) { this.userService=userService; } public UserService createProxy(){ UserService Userproxy=(UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), this);//当时这里写错了 return Userproxy; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //如果是save方法,那么就加强 if("save".equals(method.getName())){ System.out.println("权限校验成功了............."); return method.invoke(userService,args); } return method.invoke(userService,args); } }
4 Cglib动态代理的部分代码实现
package com.baidu.demo2; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CglibProxy implements MethodInterceptor { //把要增强的类传进来 CustomerDao customerDao=new CustomerDao(); public CglibProxy(CustomerDao customerDao) { this.customerDao = customerDao; } public CustomerDao createProxy(){ Enhancer enhancer=new Enhancer(); //设置父类 enhancer.setSuperclass(customerDao.getClass()); //设置回调 enhancer.setCallback(this); CustomerDao customerDao = (CustomerDao) enhancer.create(); return customerDao; } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { //判断方法是否为空 if("save".equals(method.getName())){ //增强 System.out.println("权限校验成功啦....."); return methodProxy.invokeSuper(proxy,args); } return methodProxy.invokeSuper(proxy,args); } }
5 Spring AOP的开发(基于Aspect J的XML方式)
你要想进行AOP的开发,就必须得了解一些相关的术语
Joinpoint:只要被拦截的点就成为连接点
Pointcut:切入点,真正被拦截到的点
Advice:通知、增强 增强的方法称为是通知,在方法执行之前,称为前置通知。日志记录、性能监控称为是后置通知
Introduction:引介。类层面的增强
Target:被增强的对象
Weaving:织入。通知应用(action)到目标Target的过程
Proxy:织入之后产生了一个代理对象
Aspect:切面多个通知和多个切入点的组合
6 Spring AOP的XML开发
通知类型(前三个是我们用的比较多的)
1前置通知 获得切入点的信息
2后置通知 获得返回值的类型,afterreturning
3环绕通知(功能最强的一个通知) proceed
4异常抛出通知 用于抛出异常的
5最终通知
无论有没有异常,最终通知总会执行的
(1)Aspect类
package com.baidu.demo3; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; /** * 这是一个切面类 */ public class aspetctJXMl { /** * 前置通知 * @param joinPoint */ //增强权限校验,提供增强的方法 public void checkPri(JoinPoint joinPoint) { System.out.println("权限已经校验啦....." + joinPoint); } /** * 后置通知 * @param result * @return */ public String log(Object result){ System.out.println("日志已经记录下来了....."+result); return "aa"; } /** * 环绕通知,功能最强的一个 * @param proceedingJoinPoint * @return */ public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕之前......."); Object proceed = proceedingJoinPoint.proceed(); System.out.println("环绕之后......."); return proceed; } /** * 异常抛出通知 */ public void afterThrowable(Throwable th){ System.out.println("异常抛出通知执行了....."+th); } /** * 最终通知 */ public void Final(){ System.out.println("最终通知执行了"); } }
(2)在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: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"> <!-- bean definitions here --> <bean id="productDao" class="com.baidu.demo3.ProductDaoImpl"/> <!--将切面类交给spring管理--> <bean id="aspect" class="com.baidu.demo3.aspetctJXMl"/> <!--AOP的配置--> <aop:config> <aop:pointcut id="product1" expression="execution(* com.baidu.demo3.ProductDaoImpl.save(..))"/> <aop:pointcut id="product2" expression="execution(* com.baidu.demo3.ProductDaoImpl.delete(..))"/> <aop:pointcut id="product3" expression="execution(* com.baidu.demo3.ProductDaoImpl.update(..))"/> <aop:pointcut id="product4" expression="execution(* com.baidu.demo3.ProductDaoImpl.find(..))"/> <!--配置切面--> <aop:aspect ref="aspect"> <!--前置通知--> <aop:before method="checkPri" pointcut-ref="product1"/> <!--后置通知--> <aop:after-returning method="log" pointcut-ref="product2" returning="result"/> <!--环绕通知--> <aop:around method="around" pointcut-ref="product3" /> <!--异常抛出通知--> <aop:after-throwing method="afterThrowable" pointcut-ref="product4" throwing="th"/> <!--最终通知--> <aop:after method="Final" pointcut-ref="product4"/> </aop:aspect> </aop:config> </beans>
7 SPring AOP的注解开发
(1)Aspect类
package com.baidu.demo4; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Component //组件 @Aspect //切面多个通知和多个切入点的组合 public class aspect { //声明一个公共的切入点 @Pointcut("execution(* com.baidu.demo4.UserService.*(..))") //任意返回值 任意方法 任意参数 public void myPointCut() { } //增强的方法 @Before("myPointCut()") public void log() { System.out.println("日志记录成功啦==============="); } @After("myPointCut()") public void save() { System.out.println("性能检测成功啦============="); } @AfterThrowing("myPointCut()") public void b() { System.out.println("检测出来了异常==============="); } }
(2)zhujie.xml
(3)测试类
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:zhujie.xml") public class SpringTest2 { @Resource private UserService userService; @Test public void demo(){ userService.find(); userService.save(); userService.delete(); } }
最后,附上一节的Spring框架的快速入门 https://www.cnblogs.com/bao6/p/10388760.html
英文单词:Component:组件