Spring IOC AOP学习笔记

Spring IOC AOP学习笔记

IOC
使用<constructor-arg>标签可以对构造方法的参数进行注入。
示例

<bean id="userDao" class="dao.impl.UserDaoImpl" />
<bean id="userService" class="service.impl.UserServiceImpl">        
<constructor-arg><ref bean="userDao" /></constructor-arg>
</bean>

注意
1、一个<constructor-arg>元素表示构造方法的一个参数,且使用时不区分顺序。

2、通过<constructor-arg>元素的index 属性可以指定该参数的位置索引,位置从0 开始。

3、<constructor-arg>元素还提供了type 属性用来指定参数的类型,避免字符串和基本数据类型的混淆。

使用p:对象属性注入
对于直接量(基本数据类型、字符串)属性:p:属性名=“属性值”
对于引用Bean的属性:p:属性名-ref=“Bean的id”
需要引入命名空间xmlns:p=“http://www.springframework.org/schema/p”(使用idea可以自动引入这个命名空间)
示例

<bean id="user" class="entity.User" p:age="23" p:username="张三" p:email="zhangsan@xxx.com" />
<bean id="userService" class="service.impl.UserServiceImpl" p:dao-ref="user" />

注解方式将Bean的定义信息和Bean实现类结合在一起,Spring提供的注解有
@Component:实现Bean组件的定义
@Repository :用于标注DAO类
@Service :用于标注业务类
@Controller :用于标注控制器类

使用@Autowired注解实现Bean的自动装配,默认按类型匹配,可以使用@Qualifier指定Bean的名称

使用注解信息启动Spring容器

<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"
    xsi:schemaLocation="......
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    <!-- 扫描包中注解标注的类 -->
    <context:component-scan base-package="service,dao" />
</beans>

指定需要扫描的基类包,多个包可用逗号隔开
使用注解的示例

/**

  • 用户业务类,实现对User功能的业务管理
    */
    @Service(“userService”)
    public class UserServiceImpl implements UserService {

    @Autowired // 默认按类型匹配
    @Qualifier(“userDao”) // 按指定名称匹配
    private UserDao dao;

    // 使用@Autowired直接为属性注入,可以省略setter方法
    /public void setDao(UserDao dao) {
    this.dao = dao;
    }
    /

    public void addNewUser(User user) {
    // 调用用户DAO的方法保存用户信息
    dao.save(user);
    }
    }

实体类
package entity;

/**

  • 用户实体类
    */
    public class User implements java.io.Serializable {
    private Integer id; // 用户ID
    private String username; // 用户名
    private String password; // 密码
    private String email; // 电子邮件

    // getter & setter
    public Integer getId() {
    return id;
    }

    public void setId(Integer id) {
    this.id = id;
    }

    public String getUsername() {
    return username;
    }

    public void setUsername(String username) {
    this.username = username;
    }

    public String getPassword() {
    return password;
    }

    public void setPassword(String password) {
    this.password = password;
    }

    public String getEmail() {
    return email;
    }

    public void setEmail(String email) {
    this.email = email;
    }

}

dao
package dao.impl;

import org.springframework.stereotype.Repository;

import dao.UserDao;
import entity.User;

/**

  • 用户DAO类,实现UserDao接口,负责User类的持久化操作
    */
    @Repository(“userDao”)
    public class UserDaoImpl implements UserDao {

    public void save(User user) {
    // 这里并未实现完整的数据库操作,仅为说明问题
    System.out.println(“保存用户信息到数据库”);
    }
    }
    测试
    package test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import service.UserService;

import entity.User;

public class Test {
@org.junit.Test
public void test() {
// 使用ApplicationContext接口的实现类ClassPathXmlApplicationContext加载Spring配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext(
“applicationContext.xml”);
// 通过ApplicationContext接口的getBean()方法获取id或name为userService的Bean实例
UserService service = (UserService) ctx.getBean(“userService”);

	User user = new User();
	user.setId(1);
	user.setUsername("test");
	user.setPassword("123456");
	user.setEmail("test@xxx.com");

	service.addNewUser(user);
}

}

AOP
AOP三要素:
切面(Aspect)
切点(pointcut)
切入方式(Before、After、AfterReturning、AfterThrowing)
AspectJ
面向切面的框架,它扩展了Java语言,定义了AOP 语法,能够在编译期提供代码的织入
@AspectJ
AspectJ 5新增的功能,使用JDK 5.0 注解技术和正规的AspectJ切点表达式语言描述切面
Spring通过集成AspectJ实现了以注解的方式定义增强类,大大减少了配置文件中的工作量
利用轻量级的字节码处理框架asm处理@AspectJ中所描述的方法参数名
使用注解定义前面
需求说明
使用注解来实现日志切面

使用注解定义前置增强和后置增强实现日志功能
@Aspect
@Before
@AfterReturning
编写Spring配置文件,完成切面织入
<aop:aspectj-autoproxy />:启用对于@AspectJ注解的支持
AOP增强处理类型
增强处理类型 特 点
Before 前置增强处理,在目标方法前织入增强处理
AfterReturning 后置增强处理,在目标方法正常执行(不出现异常)后织入增强处理
AfterThrowing 异常增强处理,在目标方法抛出异常后织入增强处理
After 最终增强处理,不论方法是否抛出异常,都会在目标方法最后织入增强处理
Around 环绕增强处理,在目标方法的前后都可以织入增强处理
AOP的配置元素
AOP配置元素 描 述
aop:config AOP配置的顶层元素,大多数的aop:*元素必须包含在aop:config元素内
aop:pointcut 定义切点
aop:aspect 定义切面
aop:after 定义最终增强(不管被通知的方法是否执行成功)
aop:after-returning 定义after-returning增强
aop:after-throwing 定义after-throwing增强
aop:around 定义环绕增强
aop:before 定义前置增强
aop:aspectj-autoproxy 启动@AspectJ注解驱动的切面
AOP注解

1、切入点表达式的格式:execution([可见性] 返回类型 [声明类型].方法名(参数) [异常])

2、切入点表达式通配符:
*:匹配所有字符
…:一般用于匹配多个包,多个参数
+:表示类及其子类

3、切入点表达式支持逻辑运算符:&&、||、!

4、切入点表达式关键词:
1)execution:用于匹配子表达式。
//匹配com.cjm.model包及其子包中所有类中的所有方法,返回类型任意,方法参数任意
@Pointcut(“execution(* com.cjm.model….(…))”)
public void before(){}

  2)within:用于匹配连接点所在的Java类或者包。

//匹配Person类中的所有方法
@Pointcut(“within(com.cjm.model.Person)”)
public void before(){}

//匹配com.cjm包及其子包中所有类中的所有方法
@Pointcut(“within(com.cjm…*)”)
public void before(){}

 3) this:用于向通知方法中传入代理对象的引用。

@Before(“before() && this(proxy)”)
public void beforeAdvide(JoinPoint point, Object proxy){
//处理逻辑
}
4)target:用于向通知方法中传入目标对象的引用。
@Before(“before() && target(target)”)
public void beforeAdvide(JoinPoint point, Object proxy){
//处理逻辑
}

  5)args:用于将参数传入到通知方法中。

@Before(“before() && args(age,username)”)
public void beforeAdvide(JoinPoint point, int age, String username){
//处理逻辑
}

  6)@within:用于匹配在类一级使用了参数确定的注解的类,其所有方法都将被匹配。 
        @Pointcut("@within(com.cjm.annotation.AdviceAnnotation)") - 所有被@AdviceAnnotation标注的类都将匹配
        public void before(){}

//Java代码
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Inherited
public @interface AdviceAnnotation {

}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Inherited
public @interface AdviceAnnotation {

}

  7)@target:和@within的功能类似,但必须要指定注解接口的保留策略为RUNTIME。

@Pointcut("@target(com.cjm.annotation.AdviceAnnotation)")
public void before(){}

  8)@args:传入连接点的对象对应的Java类必须被@args指定的Annotation注解标注。

@Before("@args(com.cjm.annotation.AdviceAnnotation)")
public void beforeAdvide(JoinPoint point){
//处理逻辑
}

Java代码
@AdviceAnnotation
public class Address {

}
public class Person {
public void say(Address address){
//处理逻辑
}
}

@AdviceAnnotation
public class Address {

}

如果需要在Person类的say方法被调用时触发beforeAdvide通知,那么say方法的参数对应的Java类型Address类必须要被@AdviceAnnotation标注。

  9)@annotation:匹配连接点被它参数指定的Annotation注解的方法。也就是说,所有被指定注解标注的方法都将匹配。
        @Pointcut("@annotation(com.cjm.annotation.AdviceAnnotation)")
        public void before(){}

Java代码
public class Person {
@AdviceAnnotation
public void say(Address address){
//处理逻辑
}
}

Person类的say方法被@AdviceAnnotation标注,所以它匹配。

  10)bean:通过受管Bean的名字来限定连接点所在的Bean。该关键词是Spring2.5新增的。

@Pointcut(“bean(person)”)
public void before(){}
id为person的受管Bean中的所有方法都将匹配。
使用注解切入时切面必须在spring配置文件中注册或给切面类添加@Component注解,要不然不起作用!!!!!!!!!!!!!!

<bean class="cn.madpc.log.PrintLog"/>

使用注解实现AOP需要在配置文件中配置如下内容‘

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
       <!--开启扫描器-->
    <context:component-scan base-package="cn"/>
    <!--开启自动代理-->
    <aop:aspectj-autoproxy/>
</beans>

AOP常用注解
@Aspect、@Before、@AfterReturning、@Around、@AfterThrowing、@After
使用AOP需要下面的jar包
aspectjweaver-1.6.9.jar

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

电脑狂人-菜鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值