一、回顾
1.1 依赖注入的方式。
- set方法来注入 <property name=”属性名” />
- 构造方法来注入<construtor-arg index=”” />
1.2 依赖注入的数据类型。
- 基本类型和字符串 value
- 对象类型 ref <bean></bean>
- 集合List set
- map类型 <entry key= value=>
- array类型
1.3 引入属性文件.<context: property-placeholder location=”classpath:*.properties”>
1.4 自动注入。 autowire=”byName | byType | default | no ”
1.5 bean的作用域 scope=”singleton | prototype”
1.6 注解. @Repository (持久化) @Service (业务层) @Controller (控制层) @Component (组件) ,这四个功能都是一样的。
@Autowired (自动注入 先按照类型注入,再按照名称注入) @Resource (自动注入 按照名称先注入,再按照类型注入。如果没有起名,那么它的名称就是属性的名称。)
二、AOP面向切面编程
Aop的前提:1.代理 2.AOP
1.动态代理模式
代理设计模式的原理: 使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时将方法调用转到原始对象上.
示例:
创建接口ArithmeticCalculate
public interface ArithmeticCalculate { /** * 加法 * @param a * @param b * @return */ public double add(double a,double b); /** * 减法 * @param a * @param b * @return */ public double sub(double a,double b); /** * 乘法 * @param a * @param b * @return */ public double mul(double a,double b); /** * 除法 * @param a * @param b * @return */ public double div(double a,double b); }
创建接口的实现类
package com.zhiyou100.ykq.aop.proxy; //1.使用代理(了解) 2.使用spring的aop。 public class ArithmeticCalculateImp implements ArithmeticCalculate { //在每个方法中加入日志信息。 @Override public double add(double a, double b) { double result=a+b; System.out.println("result:"+result); return result; } @Override public double sub(double a, double b) { double result=a-b; System.out.println("result:"+result); return result; } @Override public double mul(double a, double b) { double result=a*b; System.out.println("result:"+result); return result; } @Override public double div(double a, double b) { double result=a/b; System.out.println("result:"+result); return result; } }
创建代理类并实现接口来代理需要被代理的对象
//调用处理程序:InvocationHandler public class ArithmeticCalculateLogProxy implements InvocationHandler{ //被代理的对象 明星 private Object target; public ArithmeticCalculateLogProxy(Object target) { this.target = target; } /** * mothod: 正在被调用的方法 * args: 正在执行的方法所需要的参数 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName=method.getName(); System.out.println("the method "+methodName+" begin with "+Arrays.asList(args)); //method:方法 //target:目标对象 Object result=method.invoke(target, args);//回调 System.out.println("the method add end result:"+result); return result; } //得到代理对象。 经纪人 public Object getProxy() { //loader: 得到代理对象的类加载器。 //interfaces: 代理对象 要代理的方法由哪些。 //h: 当执行这些方法时,会调用该类中invoke方法 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } }
测试
public class Test { public static void main(String[] args) { ArithmeticCalculate target=new ArithmeticCalculateImp();//创建的王宝强 ArithmeticCalculateLogProxy proxy=new ArithmeticCalculateLogProxy(target); ArithmeticCalculate p=(ArithmeticCalculate) proxy.getProxy(); //宋喆 p.sub(15, 25);//1.首先执行invoke方法 } }
2.AOP模式
2.1使用注解来完成
加入依赖的jar包文件
创建一个接口ArithmeticCalculate
public interface ArithmeticCalculate { // 加法 public double add(double a,double b); // 减法 public double sub(double a,double b); // 乘法 public double mul(double a,double b); // 除法 public double div(double a,double b); }
创建实现以上接口的类
@Component public class ArithmeticCalculateImp implements ArithmeticCalculate { //在每个方法中加入日志信息。 @Override public double add(double a, double b) { double result=a+b; System.out.println("result:"+result); return result; } @Override public double sub(double a, double b) { double result=a-b; System.out.println("result:"+result); return result; } @Override public double mul(double a, double b) { double result=a*b; System.out.println("result:"+result); return result; } @Override public double div(double a, double b) { if(b==2) { throw new RuntimeException("出错了"); } double result=a/b; System.out.println("result:"+result); return result; } }
创建一个切面类
//切面类 @Aspect @Component public class LogAspect { //*:通配的是访问修饰符 //..:通配的是方法的参数,一般三个及以上 //连接点(joinpoint) //Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器 //前置通知 @Before(value="execution(* com.zhiyou100.xz.aspectj.*.*(..))")// 第一个*代表类,第二个*代表类中的方法 public void aa(JoinPoint joinPoint) { //在ArithmeticCalculateImp中add方法前执行 Object[] args=joinPoint.getArgs(); String name=joinPoint.getSignature().getName(); System.out.println("zhiyou-->the method "+name+" begin with"+Arrays.asList(args)); } //@AfterReturning //后置通知 @After(value="execution(* com.zhiyou100.xz.aspectj.*.*(..))") public void bb(JoinPoint joinPoint) { String name=joinPoint.getSignature().getName(); //joinPoint.getTarget(); System.out.println("zhiyou-->the method "+name+"end result:"); } //返回通知 @AfterReturning(value="execution(* com.zhiyou100.xz.aspectj.*.*(..))",returning="result") public void cc(Object result) { System.out.println("======"+result); } //异常通知 @AfterThrowing(value="execution(* com.zhiyou100.xz.aspectj.*.*(..))",throwing="e") public void dd(Exception e) { System.out.println("异常了:"+e.getMessage()); } }
在spring的配置文件app.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" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> <!-- 包扫描 --> <context:component-scan base-package="com.zhiyou100.xz.aspectj"></context:component-scan> <!-- 开启切面注解 --> <aop:aspectj-autoproxy /> </beans>
测试
public class Test { public static void main(String[] args) { ApplicationContext app=new ClassPathXmlApplicationContext("app.xml"); ArithmeticCalculate a=(ArithmeticCalculate) app.getBean("arithmeticCalculateImp"); a.div(10, 5); } }
2.2使用xml的方式来完成
把第一种方式中的接口、接口的实现类以及切面类中的注解全部删除,然后新建spring的配置文件app2.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" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> <!-- 定义被通知的程序类 --> <bean id="ari" class="com.zhiyou100.xz.aspectj.xml.ArithmeticCalculateImp"></bean> <!-- 定义切面类的bean --> <bean id="logAspect" class="com.zhiyou100.xz.aspectj.xml.LogAspect"></bean> <!-- 配置切面 --> <aop:config> <!-- 定义表达式切点 --> <aop:pointcut expression="execution(* com.zhiyou100.xz.aspectj.xml.*.*(..))" id="pointcut"/> <!-- 定义切面 --> <aop:aspect ref="logAspect"> <!-- 定义前置通知 --> <aop:before method="aa" pointcut-ref="pointcut"/> <aop:after method="bb" pointcut-ref="pointcut"/> <aop:after-returning method="cc" pointcut-ref="pointcut" returning="result"/> <aop:after-throwing method="dd" pointcut-ref="pointcut" throwing="e"/> </aop:aspect> </aop:config> </beans>
测试
public class Test2 { public static void main(String[] args) { ApplicationContext app=new ClassPathXmlApplicationContext("app2.xml"); ArithmeticCalculate a=(ArithmeticCalculate) app.getBean("ari"); a.div(10, 5); } }