java-Spring-IoC-AOP编程

企业级系统

大规模:用户数量多、数据规模大、功能众多

性能和安全要求高

业务复杂

灵活应变

Spring轻量级框架、JavaEE的春天,当前主流框架

一站式的企业应用开发框架

目标

使现有技术更加易用,推进编码最佳实践

内容

IoC容器

AOP实现

数据访问支持

简化JDBC/ORM框架

声明式事务

Web集成

Spring体系结构

Data Access/Integration

JDBC/ORM/OXM/JMS/Transactions

Web(MBC/Remoting)

Web/Servlet/Portlet/Struts

AOP

Aspects

Instrumentation

Core Container (Spring核心,Beans/Core/Context核心的核心

Beans/Core/Context/Expression Language

Test

Spring设计理念

Spring是面向Bean的编程

Spring两大技术

控制反转(IoC:Inversion of Control)/依赖注入(DI:Dependency Injection)

面向切面编程(AOP:Aspect Oriented Programming)

Beans:JavaBean 实体类

Core:util工具类

Context: 编程环境配置

Spring的优点

低侵入式设计

独立于各种应用服务器

依赖注入特性将组件关系透明化,降低了耦合度

面向切面编程特性允许将通用任务进行集中式处理

与第三方框架的良好整合

Spring弥补了EJB框架的不足,是J2EE的春天

Spring是面向bean的编程

Spring的两大核心技术

IoC定义和原理(控制反转)

将组件对象的控制权从代码本身转移到外部容器

组件化的思想:分离关注点,使用接口,不再关注实现

依赖的注入:将组件的构建和使用分开

【在A类中调用B类,在A类中new一个B类的对象】将B类放在一个容器中,不用再A类中

new一个。提供一个工厂(工厂中有多个类),如果A类需要某个类的实例,可以通过工

厂来实现这个类的实例。跟MyBatis中的数据库工厂一样,可以创建多个SqlSession

工厂模式:根据我们提供的我们所需的对象实例的描述,为我们返回所需要的产品

1、产品的规范 定义接口 实体类实现的方法

2、产品 实体类,实现接口

3、工厂 将实体类封装在工厂中

4、客户端/调用

如何使用Spring实现控制反转

编写HelloSpring类,输出“Hello,Spring!”

字符串“Spring”通过Spring注入到HelloSpring类中

步骤:

1、添加Spring.jar到项目中

2、编写配置文件

编写代码获取HelloSpring实例

使用Spring IoC步骤

1、导入spring jar包

commons-logging-1.1.1.jar

log4j-1.2.17.jar

spring-beans-3.2.13.RELEASE.jar

spring-context-3.2.13.RELEASE.jar

spring-core-3.2.13.RELEASE.jar

spring-expression-3.2.13.RELEASE.jar

2、创建spring 管理的类这里是HelloSpring

public class HelloSpring {

//定义变量who,它的值通过spring框架进行注入

private String who;

//定义打印方法,输出一句完整的问候

public void print(){

}

public String getWho() {

return who;

}

public void setWho(String who) {

this.who = who;

}

}

3、新建配置文件ApplicationContext.xml

配置ApplicationContext.xml文件

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd">

Spring

4、创建测试类

//利用ClassPathXmlApplicationContext获取spring配置文件

//也可以用FileSystemXmlApplicationContext读取配置文件

ApplicationContext context =

new ClassPathXmlApplicationContext("ApplicationContext.xml");

//获取配置文件中的bean

HelloSpring helloSpring = (HelloSpring)context.getBean("helloSpring");

helloSpring.print();

设置注入

使用元素定义一个组件

id属性:指定一个用来访问的唯一名称

name属性:指定多个别名,名字之间使用逗号、分号或空格进行分割

如何开发一个打印机

可灵活配置使用彩色墨盒或灰色墨盒

可灵活配置打印页面的大小

打印功能的实现依赖于墨盒和纸张

步骤

定义墨盒和纸张的接口标准

使用接口标准开发打印机

组装打印机

运行打印机

不要忘记为被注入的属性提供setter方法

AOP定义和原理

【平常一段代码有 记录日志代码,业务代码,事务控制代码,】

(我们构建系统的目的是解决业务问题,现在却要维护多个方面的事情,不能做到专一

横切逻辑,

业务代码

AOP的目标;让我们可以“专心做事”

AOP原理

将复杂的需求分解出不同的方面,将功能集中解决

采用代理机制组装起来运行,在不改变原程序的基础上对代码进行增强处理,增加新的

功能

代理对象fun(),通过代理对象来调用原对象的方法;代理对象方法前后都可插入代码,

这些代码就是增强处理

所谓面向切面编程,是一种通过预编译方式和运行期动态代理实现在不修改源代码的情

况下给程序添加功能的技术

AOP相关术语

1、增强处理(Advice)

前置增强

后置增强

环绕增强,异常抛出增强、最终增强等类型

【代理类】

+fun1() :void

+addNewUser :boolean

+fun2(): void

2、切入点(Pointcut)是系统要增强处理的点,就是连接点的查询条件

3、连接点(Join Point)

4、切面(Aspect)

5、目标对象(Target object)被增强的类

6、AOP代理(AOP proxy)代理类

7、织入(Weaving)将切入点插入增强处理

AOP实现自动的系统日志功能

使用Spring AOP实现日志输出

在业务方法执行前后成功添加了日志功能

实现步骤

1、在项目添加Spring AOP的jar文件

commons-logging-1.1.1.jar

log4j-1.2.17.jar

spring-beans-3.2.13.RELEASE.jar

spring-context-3.2.13.RELEASE.jar

spring-core-3.2.13.RELEASE.jar

spring-expression-3.2.13.RELEASE.jar

aopalliance-1.0.jar

aspectjweaver-1.6.9.jar

spring-aop-3.2.13.RELEASE.jar

2、编写前置增强和后置增强实现日志功能(编写处理类)

3、编写Spring配置文件,对业务方法进行增强处理

4、编写代码获取带有增强处理的业务对象

Spring中IoC机制是在配置文件中就可以进行参数的传递,无需在外面传参。特别是参数

是实体类的,可以直接在配置文件中引用,不需要外面创建一个类,再调用。

public class User {

private Child child;

public void add(){

child.get();

}

public void setChild(Child child){

this.child = child;

}

/*public void add(Child child){

child.get();

}*/

}

public void add(Child child){

child.get();

}本来需要用这个将对象传到User类进去的,

Child child = new Child();

User user = new User();

user.add(child);

现在通过配置文件直接调用Child类,无需new一个类

name="child"是上面方法public void setChild(Child child)中的setChild的Child

ref="_child"将类引用到User类中,通过setChild方法得到该类

public class Child {

public void get(){

}

}

@Test

public void testUser() {

//利用ClassPathXmlApplicationContext获取spring配置文件

//也可以用FileSystemXmlApplicationContext读取配置文件

ApplicationContext context =

new ClassPathXmlApplicationContext("ApplicationContext.xml");

//利用context对象中的getBean()方法获得里面配置的类

User user = (User) context.getBean("user");

user.add();

}

在Spring配置文件中通过元素为构造方法传参

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

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

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

据类型的混淆

hello

world

设置注入:

通过setter访问器实现

灵活性好,但setter方法数量较多

时效性差

通过无参构造实例化

构造注入:

通过构造方法实现

灵活性差、仅靠重载限制太多

时效性好

通过匹配构造方法实例化,但建议保留无参构造方法

p命名空间的特点:使用属性而不是子元素的形式配置Bea的属性,从而简化配置代码

对于直接量(基本数据类型、字符串)属性:p:属性名=“属性值”

对于引用Bean的属性:p:属性名-ref="Bean的id"

使用前要先要在Spring配置文件中引入p命名空间

xmlns:p="http://www.springframework.org/schema/p"

使用p命名空间注入属性值

ref="userDao" />

注入不同数据类型

1、注入直接量

使用标签实现

注意特殊字符的处理

2、引用Bean

使用标签实现

注意bean属性和local属性的区别【当项目很大时,会有多个配置文件,local

表示本文件】

3、使用内部Bean

4、注入集合类型的属性

分别使用

///

标签实现

5、注入null和空字符串值

使用 注入Null值

使用注入空字符串值

P&G

足球

篮球

足球

篮球

足球

篮球

football

足球

basketball

篮球

足球

篮球

异常抛出增强的特点

1、在目标方法抛出异常时织入增强处理

2、可拔插的异常处理方案

元素:定义异常抛出增强

ponitcut-ref="pointcat" throwing="e" />

method="afterThrowing" 是AOPException类中的方法名

public class AOPException {

public void afterThrowing(JoinPoint jp,RuntimeException e){

()+":"+e.getMessage());

}

}

最终增强的特点

1、无论方法是否抛出异常,都会在目标方法最后织入增强处理,即:该增强都会得到执

2、类似异常处理机制中finally块的作用,一般用于释放资源

3、可以为各功能模块提供统一的,可拔插的处理方案

元素:定义最终增强

最终增强处理类

public class AOPAfter {

public void after(JoinPoint jp){

");

}

}

环绕增强的特点

1、目标方法前后都可织入增强处理

2、功能最强大的增强处理

3、可获取或修改目标方法的参数、返回值,可对它进行异常处理,甚至可以决定目标方

法是否执行

元素:定义环绕增强

增强处理类

public class AOPAround {

public Object around(ProceedingJoinPoint pjp) throws Throwable{

+pjp.getSignature()+"目标方法.方法参数"+Arrays.toString

(pjp.getArgs()));

Object result;

try{

result = pjp.proceed();

+pjp.getSignature()+"目标方法.方法

返回值"+result);

return result;

}

catch(Throwable e)

{

方法发生异常"+e);

throw e;

}

finally

{

方法发生结束");

}

}

}

常用增强处理类型(主要是一些功能型,日志管理、异常处理、资源释放)

Before 前置增强处理,在目标方法前织入增强处理

AfterReturning 后置增强处理,在目标方法正常执行后织入增强处理(不出现异常情

况下,出现异常后置增强不会发生)

AfterThrowing: 异常增强处理,在目标方法抛出异常后织入增强处理

After :最终增强处理,不论方法是否抛出异常,都会在目标方法最后织入增强处理

Around 环绕增强处理,在目标方法前后都可以织入增强处理

SpringAOP配置元素

AOP配置的顶层元素,大多数的必须包含在元素

定义切点(一般是业务层方法)

定义切面,在切面中进行增强处理类的配置

定义最终增强

定义后置增强

定义异常增强

定义环绕增强

定义前置增强

启动AspectJ注解驱动的切面

使用注解实现IoC的方法(无需在配置文件中配置Bean信息)

注解方式将Bean的定义信息和Bean实现类结合在一起,Spring提供注解有:

@Component:实现Bean组件的定义

@Repository:标注DAO类

@Service:标注业务类

@Controller:标注控制器类

@Repository("userDao") 加了这个等效于在

public class UserDaoImpl implements UserDao{

.....................

}

@Repository("userDao") 加了这个等效于在XML文件编写

使用@Autowired注解执行Bean的自动装配,默认按类型匹配

可以使用@Qualifier指定Bean的名称

第一种方法:

@Service("useServic")

public class UserServiceImpl implements UserService{

@Autowired

@Qualifier("userDao")

private UserDao dao;

.....

}可以对类的成员变量进行标注

第二种方法:

@Service("useServic")

public class UserServiceImpl implements UserService{

private UserDao dao;

@Autowired

public void setDao(@Qualifier("userDao")UserDao dao){

this.dao = dao;

}这种方式可以用在构造方法上面

............

}将UserDao对象引入到UserServiceImpl,相当于配置文件下面的代码

注:@Autowired(required=false) 默认是true,当@Qualifier("userDao2")userDao2

未找到,程序不报错会返回一个空指针

使用注解信息启动Spring容器

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">

package="org.demo">

package="org.demo"注解类所在的包,多个用逗号分隔

使用@Resource注解执行组件装配,默认按属性名称匹配,如果属性名找不到,就按类型

名找

第一种方法

@Service("useServic")

public class UserServiceImpl implements UserService{

@Resource(name="userDao")//通过@Resource注解实现装配

private UserDao dao;

.....

}

第二种方法

public class UserServiceImpl implements UserService{

private UserDao dao;

@Resource(name="userDao")//通过@Resource注解实现装配

public void setDao(UserDao dao){

this.dao = dao;

}

............

}

使用注解实现AOP

AspectJ

面向切面的框架,它扩展了Java语言,定义了AOP语法,能够在编译期提供代码的织入

@AspectJ

AspectJ5新增的功能,使用JDK5.0注解技术和正规的AspectJ切点表达式语言描述切面

注:使用@AspectJ,首先保证所用的JDK是5.0或以上的版本

Spring通过集成AspectJ实现了以注解的方式定义增强类,大大减少了配置文件中的工

作量

利用轻量级的字节码处理框架asm处理@AspectJ中所描述的方法参数名

需求说明(使用注解实现日志切面)

使用注解定义前置增强和后置增强实现日志功能

@Aspect

@Before

@AfterReturning

编写Spring文件,完成切面织入

:启用对于@AspectJ注解的支持

@Aspect //定义切面

public class UserServiceLogger {

private static Logger log = Logger.getLogger

(UserServiceLogger.class);

/*//前置增强

@Before("execution(void org.demo.UserImpl.addUser(User))")

public void before(JoinPoint jp){

log.info("调用" + jp.getTarget() + "的"+ jp.getSignature

() +

"方法.方法参数" + Arrays.toString

(jp.getArgs()));

}

//后置增强

@AfterReturning(pointcut="execution(void

org.demo.UserImpl.addUser(User))",

returning="result")

public void AfterReturningTest(JoinPoint jp,Object result){

log.info("调用" + jp.getTarget() + "的"+ jp.getSignature

() +

"方法.方法返回值" + result);

}*/

//切入点的统一定义

@Pointcut("execution(void org.demo.UserImpl.addUser(User))")

public void pointcut(){}

//前置增强

@Before("pointcut()")

public void before(JoinPoint jp){

log.info("调用" + jp.getTarget() + "的"+ jp.getSignature

() +

"方法.方法参数" + Arrays.toString

(jp.getArgs()));

}

//后置增强

@AfterReturning(pointcut="pointcut())",returning="result")

public void AfterReturningTest(JoinPoint jp,Object result){

log.info("调用" + jp.getTarget() + "的"+ jp.getSignature

() +

"方法.方法返回值" + result);

}

}

配置文件

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">

使用注解进行异常增强

@AfterThrowing

使用注解进行最终增强

@After

使用注解进行环绕增强

@Around

使用注解方式定义切面可以简化配置工作量

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180415G1AXLW00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券