Spring_IoC注解开发和AOP的XML开发(学习笔记2)

一:IoC注解开发

1,在applicationContext.xml中需要引入context约束

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

2,简单的注解开发实例

  <!-- 进行IoC注解开发,首先在配置文件里配置组件扫描,即哪个包下的类进行注解开发 -->  
	<context:component-scan base-package="com.test.spring.demo1"/>
@Component("userDao")
public class UserDaoImp implements UserDao { @Value("三八") private String name; @Override public void save() { System.out.println("UserDaoImp的save方法执行了"+name); } } 

注意:对于要实现的类中的属性注入,可以不提供该属性的set方法,如果提供了,将@Value的注解加在set方法上发即可

3,IoC注解详情

@Component 

修饰一个类,将这个类交给Spring管理,有三个衍生注解(功能相似)建议用衍生的三个注解

  1. @Controller(web 层)
  2. @Service(service 层)
  3. @Repository(dao 层)
@Repository("userDao")
public class UserDaoImp implements UserDao { @Value("三八") private String name; @Override public void save() { System.out.println("UserDaoImp的save方法执行了"+name); } } 

属性注入的注解

  • @Value(” “)注入普通属性,并设置属性的值
  • @Autowired    注入对象属性,根据对象类型来注入,但一般是按照名称来注入,需要搭配注解@Qualifier(value="名称” 
  • @Resource(name="名称")  根据名称注入对象属性,常用
@Service("userService")
public class UserServiceImp implements UserService { //注入UserDao /*@Autowired @Qualifier(value="userDao")*/ @Resource(name="userDao") private UserDao userDao; @Override public void save() { System.out.println("UserService的save方法执行了"); userDao.save(); } } 

其他注解:

  • @PostConstruct   初始化方法
  • @PreDestroy  销毁方法
  • @Scope("singleton&prototype&request&session&globalsession")  作用范围的注解,默认为singleton,单例
@Service("customerService")
@Scope
public class CustomerServiceImp implements CustomerService { @PostConstruct public void Init(){ System.out.println("init"); } @Override public void save() { } @PreDestroy public void Destroy(){ System.out.println("destroy"); } }

4,xml和注解的区别和整合开发

注解与XML配置的区别

注解:是一种分散式的元数据,与源代码紧绑定。

xml:是一种集中式的元数据,与源代码无绑定。

详情:https://www.cnblogs.com/iOS-mt/p/6133656.html

xml和注解的整合开发(了解)

注意:bean管理交给xml,属性注入交给注解

<bean id="customerService" class="com.test.spring.demo2.CustomerServiceImp"/> <bean id="productDao" class="com.test.spring.demo2.ProductDao"/> <!-- 需要开启以下配置,在没有扫描的情况下,能够使用注解将属性注入 @Value @Resource @Autowired @Qualifier--> <context:annotation-config />

 二,AOP(Aspect Oriented Programming)面向切面编程

参考:http://www.cnblogs.com/xrq730/p/4919025.html

AOP的作用简单图示:

1,底层原理为动态代理(反射)

  • JDK动态代理:只能对实现了接口的类进行代理
  • Cglib动态代理:(类是于Javasist第三方代理技术),可以对没有实现接口的类实现代理,生成子类对象
//Cglib动态代理简单实现,增强UserDao中的save方法
public class UserDaoProxy implements MethodInterceptor{ private UserDao userDao; public UserDaoProxy(UserDao userDao) { super(); this.userDao = userDao; } public UserDao createProxy(){ //1,获取Cglib动态代理核心类 Enhancer enhancer=new Enhancer(); //2,设置父类 enhancer.setSuperclass(userDao.getClass()); //3,设置回调:(类似于 InvocationHandler对象) enhancer.setCallback(this); //4,创建代理对象 UserDao proxy = (UserDao) enhancer.create(); return proxy; } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { if("save".equals(method.getName())){ System.out.println("增强代码"); return methodProxy.invokeSuper(proxy, args); } return methodProxy.invokeSuper(proxy, args); } } 

2,AOP的相关术语:

  • Joinpoint(连接点,可以被增强/切入的方法都可以被称为连接点)
  • Pointcut(切入点,真正被增强的连接点被称为切入点)
  • Advice(通知/增强,增强的相关代码或方法)
  • Introduction(引介,类层面的增强,即向类里直接加入增强的代码)
  • Target(目标,被增强的对象)
  • weaving(织入,将Advice引入到Target的过程)
  • Proxy(代理,通过AOP织入后的类)
  • Aspect(切面,多个通知和多个切入点的组合)

注意:切入点可以是一个包下的单个类的单个方法,也可以是一个或多个包下的多个类的多个方法,需要灵活配置

3,基于aspectJ的aop的xml开发简单入门

1)引入相应的jar包

2)在配置文件中引入aop的schema约束

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

3)编写目标类

public class ProductDaoImp implements ProductDao { @Override public void save() { System.out.println("product保存"); } @Override public void delete() { System.out.println("product删除"); } } 

4)编写切面类

public class MyAspectXml {
	public void checkPriviledge(){ System.out.println("权限校验代码========="); } } 

5)xml的配置

        <!-- 配置目标对象 -->
	<bean id="productDao" class="com.test.demo1.ProductDaoImp"></bean> <!-- 配置切面类 --> <bean id="myAspect" class="com.test.demo1.MyAspectXml"></bean> <!-- 配置AOP对目标对象产生代理 --> <aop:config> <!-- 配置切入点 --> <aop:pointcut expression="execution(* com.test.demo1.ProductDaoImp.save(..))" id="pointcut1" /> <!-- 配置切面 --> <aop:aspect ref="myAspect"> <aop:before method="checkPriviledge" pointcut-ref="pointcut1" /> </aop:aspect> </aop:config>

4,advice(通知)类型

1)前置通知

仅能获取到切入点信息(所有类型的通知都可以获取)

public class MyAspectXml {
	public void checkPriviledge(JoinPoint joinpoint){ System.out.println("权限校验代码========="+joinpoint); } }

2)后置通知

能够获取切入点的返回值

public void writeLog(Object obj){ System.out.println("日志代码========="+obj); }
<!-- 后置通知 -->
<aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="obj"/> 

3)环绕通知

在切入点的前后都执行相关的增强代码,可以阻止切入点的执行(如对切入点进行事务处理)

public void round(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("环绕前代码========"); //执行切入点的方法 joinPoint.proceed(); System.out.println("环绕后代码========"); }
 <!-- 环绕通知 -->
<aop:around method="round" pointcut-ref="pointcut3"/> 

4)异常通知

当所应用/通知的切入点,运行异常时,会执行异常通知,也可以对异常抛出

public void afterThrowing(Throwable ex){ System.out.println("异常抛出通知代码====="+ex.getMessage()); }
  <!-- 异常通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/> 

5)最终通知

无论切入点是否有异常,最终通知的代码都会执行

 <!-- 最终通知 -->
<aop:after method="after" pointcut-ref="pointcut4"/>

5,切入点表达式

execution([访问修饰符] 访问返回值类型 包名.类名.方法名(参数))

访问修饰符可以省略,访问返回值类型可以用 * 代替,表示任意类型,参数 .. 代替,表示任意参数 用 * 可以灵活配置切入点

例: * *.*.*(..)  表示任意包的的所有类下的说有方法配置为一个切入点

        * com.test.dao.UserDao+.save(..) 表示UserDao类及其子类的save方法配置为一个切入点

猜你喜欢

转载自www.cnblogs.com/wuba/p/11028437.html