一、Spring的IOC注解开发
1.1 环境搭建
Spring4版本中,还需引入aop的包

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" 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"> <!-- bean definitions here -->
</beans>
ProductDao.java
package com.spring.demo01;
public interface ProductDao {
public void save();
}
ProductDaoImpl.java
需配置Component属性
package com.spring.demo01;
import org.springframework.stereotype.Component;
@Component("productDao") //相当于在配置文件方式<bean id="productDao" class="com.spring.demo01.ProductDaoImpl">
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println("ProductDaoImpl保存了商品");
}
}
配置文件配置组件扫描信息
<?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" 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"> <!-- bean definitions here -->
<!-- Spring IOC的注解方式, -->
<!-- 需配置组件扫描, 意思为配置包的类使用注解 -->
<context:component-scan base-package="com.spring.demo01"></context:component-scan>
</beans>
TestDemo01.java
package com.spring.demo01;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
/**
* Spring的IOC注解开发的测试类
* @author cf
*
*/
public class TestDemo01 {
@Test
//Spring的IOC的注解方式
public void demo01() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
ProductDao productDao = (ProductDao) applicationContext.getBean("productDao");
productDao.save();
}
}
结果如下:

二、注解方式设置属性的值
- 有set方法
在set方法出设置注解
ProductDaoImpl.java
package com.spring.demo01;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("productDao") //相当于在配置文件方式<bean id="productDao" class="com.spring.demo01.ProductDaoImpl">
public class ProductDaoImpl implements ProductDao {
private String name;
@Value("Model S")
public void setName(String name) {
this.name = name;
}
@Override
public void save() {
System.out.println("ProductDaoImpl保存了商品" + name);
}
}
结果如下:

- 无set方法
在属性值上设置注解
package com.spring.demo01;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("productDao") //相当于在配置文件方式<bean id="productDao" class="com.spring.demo01.ProductDaoImpl">
public class ProductDaoImpl implements ProductDao {
@Value("Tesla Model S")
private String name;
/*
* @Value("Model S") public void setName(String name) { this.name = name; }
*/
@Override
public void save() {
System.out.println("ProductDaoImpl保存了商品" + name);
}
}
结果如下:

三、注解详解
3.1 @Component : 组件
@Component:注解一个类,将此类交给Spring管理
有三个衍生注解:
- @Controller : web层
- @Service : service层
- @Repository : dao层
以上注解与@Component功能相同,只是为了更好的分层
上述事例中的@Component应该修改为@Repository
3.2 属性注入的注解
- 普通注解
@Value : 设置普通属性的值
- 对象类型的注解
@Autowired : 设置对象类型注解,从下例可以看到并没有相关class的路径属性,因为是按类型完成注入
创建ServiceDao.java和ServiceDaoImpl.java
package com.spring.demo01;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.sun.tracing.dtrace.Attributes;
@Service("productService")
public class ProductServiceImpl implements ProductService {
//注入productDao
@Autowired
private ProductDao productDao;
@Override
public void save() {
System.out.println("ProductServiceImpl启动了");
productDao.save();
}
}
结果如下:

@Qualifier : 强制按名称完成注入,在@Atuowired注解的基础上添加
@Service("productService")
public class ProductServiceImpl implements ProductService {
//注入productDao
@Autowired
@Qualifier("productDao")
private ProductDao productDao;
@Override
public void save() {
System.out.println("ProductServiceImpl启动了");
productDao.save();
}
}
@Resource : 可以直接使用Resource用名称实现注入
@Service("productService")
public class ProductServiceImpl implements ProductService {
//注入productDao
/*
* @Autowired
*
* @Qualifier("productDao")
*/
@Resource(name="productDao")
private ProductDao productDao;
@Override
public void save() {
System.out.println("ProductServiceImpl启动了");
productDao.save();
}
}
3.3 Bean的作用范围注解
@Scope : 作用范围
singleton : 默认,单例
prototype : 多例
reqeust:Spring创建类后,将类存入request的范围中,应用在web项目中
session:同request,放入session范围中
globalsession:在porlet环境下(子网站)使用,如果无此环境,则相当于session,应用在web项目
四、Spring的AOP
AOP : Aspect Oriented Programming,面向切面编程。
4.1 AOP的XML的方式入门案例
引入jar包

引入AOP约束:
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: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 -->
</beans>
ProductDaoImpl.java
package com.spring4_AOP.demo01;
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println("保存商品");
}
@Override
public void update() {
System.out.println("更新商品");
}
@Override
public void find() {
System.out.println("查找商品");
}
@Override
public void delete() {
System.out.println("删除商品");
}
}
切面类,MyAspectXML.java
package com.spring4_AOP.demo01;
/**
* 切面类
* @author cf
*
*/
public class MyAspectXML {
//封装通知的方法
public void checkPri() {
System.out.println("已校验操作权限");
}
}
配置文件 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: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.spring4_AOP.demo01.ProductDaoImpl"></bean>
<!-- 将切面类交给Spring管理 -->
<bean id="myAspect" class="com.spring4_AOP.demo01.MyAspectXML"></bean>
<!-- 配置目标类的代理 -->
<aop:config>
<!-- 表达式配置类和方法进行增强 -->
<aop:pointcut expression="execution(* com.spring4_AOP.demo01.ProductDaoImpl.save(..))" id="pointcut01"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspect">
<aop:before method="checkPri" pointcut-ref="pointcut01"/>
</aop:aspect>
</aop:config>
</beans>
测试类,使用了Spring整合Junit测试,需引入lib下的spring-test-4.2.4.RELEASE.jar:
package com.spring4_AOP.demo01;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestDemo01 {
@Resource(name="productDao")
private ProductDao productDao;
@Test
public void demo01() {
productDao.save();
productDao.update();
productDao.find();
productDao.delete();
}
}
结果如下:

4.2 通知类型
- 前置通知:在目标方法执行之前进行操作
入门案例中使用的是前置通知,可以获得切入点的信息
切面类MyAspectXML.java加入切入点信息显示
public class MyAspectXML {
//封装通知的方法
public void checkPri(JoinPoint joinPoint) {
System.out.println("已校验操作权限" + joinPoint);
}
}
结果如下:

- 后置通知:在目标方法执行之后进行操作
可以获得切入点的信息及方法的返回值
配置文件内容修改:
<!-- 配置目标类的代理 -->
<aop:config>
<!-- 表达式配置类和方法进行增强 -->
<aop:pointcut expression="execution(* com.spring4_AOP.demo01.ProductDaoImpl.save(..))" id="pointcut01"/>
<aop:pointcut expression="execution(* com.spring4_AOP.demo01.ProductDaoImpl.delete(..))" id="pointcut02"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspect">
<!-- 配置前置切面 -->
<aop:before method="checkPri" pointcut-ref="pointcut01"/>
<!-- 配置后置切面 -->
<aop:after-returning method="writeLog" pointcut-ref="pointcut02" returning="result"/>
</aop:aspect>
</aop:config>
MyAspectXML.java增添以下方法
//后置通知的方法
public void writeLog(Object result) {
System.out.println("日志文件已记录" +"---" + result);
}
ProductDaoImpl.java改写delete方法,增设返回值
@Override
public String delete() {
System.out.println("删除商品");
return "记录删除";
}
结果如下:

- 环绕通知:在目标方法执行之前和之后都进行操作
环绕通知可以阻止目标方法的执行
MyAspectXML.java文件增加方法
//性能监控
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕通知开始前通知");
Object object = joinPoint.proceed();
System.out.println("环绕通知结束后通知");
return object;
}
applicationContext.xml配置文件修改配置
<!-- 配置目标类的代理 -->
<aop:config>
<!-- 表达式配置类和方法进行增强 -->
<aop:pointcut expression="execution(* com.spring4_AOP.demo01.ProductDaoImpl.save(..))" id="pointcut01"/>
<aop:pointcut expression="execution(* com.spring4_AOP.demo01.ProductDaoImpl.delete(..))" id="pointcut02"/>
<aop:pointcut expression="execution(* com.spring4_AOP.demo01.ProductDaoImpl.update(..))" id="pointcut03"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspect">
<!-- 配置前置切面 -->
<aop:before method="checkPri" pointcut-ref="pointcut01"/>
<!-- 配置后置切面 -->
<aop:after-returning method="writeLog" pointcut-ref="pointcut02" returning="result"/>
<!-- 配置环绕切面 -->
<aop:around method="around" pointcut-ref="pointcut03"/>
</aop:aspect>
</aop:config>
结果如下:

- 异常抛出通知:在程序出现异常的时候进行的操作
切面类修改
//异常通知
public void afterThrowing(Throwable ex) {
System.out.println("抛出了异常" + "---" + ex);
}
实现类方法修改:
@Override
public void find() {
System.out.println("查找商品");
int i=1/0;
}
配置文件applicationContext.xml
<!-- 配置目标类的代理 -->
<aop:config>
<!-- 表达式配置类和方法进行增强 -->
<aop:pointcut expression="execution(* com.spring4_AOP.demo01.ProductDaoImpl.save(..))" id="pointcut01"/>
<aop:pointcut expression="execution(* com.spring4_AOP.demo01.ProductDaoImpl.delete(..))" id="pointcut02"/>
<aop:pointcut expression="execution(* com.spring4_AOP.demo01.ProductDaoImpl.update(..))" id="pointcut03"/>
<aop:pointcut expression="execution(* com.spring4_AOP.demo01.ProductDaoImpl.find(..))" id="pointcut04"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspect">
<!-- 配置前置切面 -->
<aop:before method="checkPri" pointcut-ref="pointcut01"/>
<!-- 配置后置切面 -->
<aop:after-returning method="writeLog" pointcut-ref="pointcut02" returning="result"/>
<!-- 配置环绕切面 -->
<aop:around method="around" pointcut-ref="pointcut03"/>
<!-- 配置异常切面 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut04" throwing="ex"/>
</aop:aspect>
</aop:config>
结果如下:

- 最终通知:无论代码是否有异常都会进行的操作
切面类:
//最终通知
public void finallyAnn() {
System.out.println("此句一定会执行");
}
配置增加:
<!-- 配置最终切面 -->
<aop:after method="finallyAnn" pointcut-ref="pointcut04"/>
结果如下:

4.3 切入点表示式
语法:
(1)基于execution函数
(2)
[访问修饰符] 方法返回值 包名.类名.方法名(参数),如下所示
execution( public void com.spring4_AOP.demo01.ProductDaoImpl.save(..))
public void 可以省略,上例均省略,使用*代替,如下所示
execution(* com.spring4_AOP.demo01.ProductDaoImpl.save(..)
save(…)表示任意参数,可以拦截指定类的所有方法,如下所示:
execution(* 包名.类名.*(..))
五、AOP的注解开发
5.1 注解开发入门案列
jar同第四节相同。
配置文件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: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 -->
<!-- 在配置文件中开启注解的AOP开发 -->
<aop:aspectj-autoproxy />
<!--配置目标类 -->
<bean id="productDao" class="com.spring4_AOP.demo01.ProductDao">
</bean>
<!-- 配置切面类 -->
<bean id="myAspect" class="com.spring4_AOP.demo01.MyAspectAnno">
</bean>
</beans>
ProductDao.java
package com.spring4_AOP.demo01;
public class ProductDao {
public void save() {
System.out.println("保存订单");
}
public void update() {
System.out.println("更新订单");
}
public void delete() {
System.out.println("删除订单");
}
public void find() {
System.out.println("查询订单");
}
}
切面类MyAspectAnno.java
package com.spring4_AOP.demo01;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
/**
* 注解方式的切面类
* @author cf
*
*/
@Aspect
public class MyAspectAnno {
@Before(value = "execution(* com.spring4_AOP.demo01.ProductDao.save(..))")
public void before() {
System.out.println("前置通知。。。");
}
}
测试类TestDemo01.java
package com.spring4_AOP.demo01;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestDemo01 {
@Resource(name="productDao")
private ProductDao productDao;
@Test
public void demo01() {
productDao.save();
productDao.update();
productDao.delete();
productDao.find();
}
}
结果如下:

5.2 注解的AOP通知类型
-
@Before : 前置通知
入门案列为前置通知
-
@AfterReturning : 后置通知
MyAspectAnno.java添加后置通知方法
//后置通知
@AfterReturning(value = "execution(* com.spring4_AOP.demo01.ProductDao.delete(..))",returning="result")
public void afterReturning(Object result) {
System.out.println("后置通知。。。文件被删除" + "---" + result);
}
运行结果如下:

-
@Around : 环绕
//环绕通知 @Around(value = "execution(* com.spring4_AOP.demo01.ProductDao.update(..))") public Object around(ProceedingJoinPoint jointPoint) throws Throwable { System.out.println("环绕前"); Object obj = jointPoint.proceed(); System.out.println("环绕后"); return obj; }
结果:

- @AfterThrowing
异常抛出
//异常抛出通知
@AfterThrowing(value = "execution(* com.spring4_AOP.demo01.ProductDao.find(..))")
public void afterThrowing() {
System.out.println("异常抛出通知");
}
- @After
最终通知
//最终通知
@After(value="execution(* com.spring4_AOP.demo01.ProductDao.find(..))")
public void after() {
System.out.println("最终通知");
}
8348



被折叠的 条评论
为什么被折叠?



