Spring AOP初试

来源:互联网 发布:知柏地黄丸成分 编辑:程序博客网 时间:2024/05/01 21:09

AOP基本概念

切面(Aspect):组织多个通知(增强处理,切面方法,advice)
连接点(Joinpoint):程序执行中明确的点,大概理解成程序执行中的点吧,比如方法执行,异常抛出。Spring AOP中就是方法调用。
通知(增强处理、切面方法、advice):有around、before、after、after returning、after throwing。
切入点(Point Cut):可以插入advice的JoinPoint。当某个连接点满足要求时,该连接点被添加上增强处理。
引入:将方法或字段添加到类中。Spring允许将新的接口引入到任何被处理的类中。
目标对象:被AOP框架进行增强处理的对象。Spring中的AOP代理可以是JDK动态代理(实现接口的目标对象),也可以是cglib代理(不实现接口的目标对象)。
织入(weaving):将增强处理添加到目标对象中,并创建一个被增强对象(AOP 代理)的过程就是织入。织入有两种方式:编译时增强(AspectJ)和运行时增强(如spring AOP)。

使用注解加配置实现

利用IDEA新建web+maven工程

配置信息

web.xml:

<context-param>    <param-name>contextConfigLocation</param-name>    <param-value>classpath*:applicationContext.xml</param-value></context-param><listener>    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>

applicationContext.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:context="http://www.springframework.org/schema/context"       xmlns:aop="http://www.springframework.org/schema/aop"       xmlns:mvc="http://www.springframework.org/schema/mvc"       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       http://www.springframework.org/schema/mvc       http://www.springframework.org/schema/mvc/spring-mvc.xsd">    <context:annotation-config />    <context:component-scan base-package="com.mitsuhide.*" />    <!--</context:component-scan>-->    <aop:aspectj-autoproxy/>    <mvc:annotation-driven /></beans>

注意:applicationContext.xml 如果是用maven配置的,一定要放在resource中,否则classpath*或者classpath找不到的。

pom.xml(IDEA的maven实在是好用,最喜欢这点)
加入了(好像aop的只有aop和aspectJ、cglib):

spring-contextspring-webmvcspring-webspring-aopaspectjrtaspectjweaverspring-txspring-aspectscglib-nodep

关键代码

Controller

@Controller@RequestMapping("/mvc")public class HelloController {    @RequestMapping("/hello")    public @ResponseBody String hello () {        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");//        Athlete zly = (Athlete)context.getBean("Athlete");        Player zly = (Player)context.getBean("Athlete");        return zly.sayHello();    }}

这里有个很有意思的事情,因为Athlete 被绑在切面方法中了,所以获取bean这里需要分情况:
1、Athlete实现了接口
这种情况走的是JDK动态代理,获取bean其实是获取的接口,向上转型了:

Player zly = (Player)context.getBean("Athlete");

2、Athlete一个接口都没实现
这种情况走的是cglib的方式,直接获取类:

Athlete zly = (Athlete)context.getBean("Athlete");

Aspect

@Aspect@Componentpublic class PlayerAspect extends CustomizableTraceInterceptor {    @Pointcut("execution( * com.mitsuhide.entity.common.Athlete.*(..))")    private void aspectMethod(){}//定义一个切入点    @Before("aspectMethod()")    public void before () {        System.out.println("方法执行前执行...... By mitsuhide aspect.");    }    @After("aspectMethod()")    public void after () {        System.out.println("方法执行后执行...... By mitsuhide aspect.");    }}

这里也可以这样写(可以实现接口也可以不实现,因为网上搜的好多教程都是实现了的):

@Before("execution( * com.mitsuhide.entity.common.Athlete.*(..))")

Bean:

@Component("Athlete")public class Athlete implements Player {    @Autowired    private Basketball ball;    public Basketball getBall() {        return ball;    }    public void setBall(Basketball ball) {        this.ball = ball;    }    public String sayHello () {        String helloWords = "Hi, I am a " + ball.getBallName() + " player";        return helloWords;    }    @PostConstruct    public void init () {        System.out.println("Athlete bean is initializing! By mitsuhide.");    }    @PreDestroy    public void destroy () {        System.out.println("Athlete bean is destroying! By mitsuhide.");    }}

遇到的问题

1、applicationContext.xml找不到

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

报找不到文件错误,这个是因为maven路径的问题。把xml文件放到resource目录下可解决。

2、切面方法不执行
切面类要同时加上@Aspect,@Component才会执行切面方法。网上教程大多只有·Aspect,我也不造为啥。

3、上面说的需要区分是接口的代理还是类的代理
网上也有另外一种解决办法:

在aop:config标签中添加 proxy-target-class=”true” 即可。
由于生成代理类有两种方式:JDK和CGLIB,一种是基于接口的,一种是基于类的。
如果添加上面的属性则使用基于类的cglib的方式,相反,如果没有写或者是false则通过jdk的基于接口的方式生成代理类。
当然,如果本身不是基于接口的,那么会自动使用cglib的方式,在这里很奇怪为什么没有自动走cglib的方式。
如果proxy-target-class 属性值被设置为true,那么基于类的代理将起作用(这时需要cglib库)。如果proxy-target-class属值被设置为false或者这个属性被省略,那么标准的JDK 基于接口的代理将起作用。

遗留的问题

spring中context的获取有好几种方式:
ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(EntityManager.class);

EntityManager:

@Configuration@ComponentScan(basePackages = {"com.mitsuhide.*"})public class EntityManager {}

@Configuration,@ComponentScan是啥,需要讨论。

0 0
原创粉丝点击