您的位置:首页 > 编程语言 > Java开发

spring入门——慕课网

2017-02-06 09:21 141 查看
慕课网,spring入门篇

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

边看边编写的代码:

http://download.csdn.net/detail/fulq1234/9754355

**2-1:IOC及Bean容器**

1.IOC是接口编程

2.接口:OneInterface

  实现类:OneInterfaceImpl

  spring-ioc.xml:
<bean id="oneInterface" class="com.imooc.ioc.interfaces.OneInterfaceImpl"></bean>


  测试类:
OneInterface temp=(OneInterface)ac.getBean("oneInterface");


3.Bean容器初始化

  文件

FileSystemXmlApplicationContext context=new FileSystemXmlApplicationContext("F:/workspace/appcontext.xml");

//classpath

ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("classpath:spring-context.xml");

Web应用 

<web-app>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-start>1</load-on-start>
</servlet>
</web-app>


**2-2:Spring注入方式**

1.设值注入:自动调用类的set方法

 
<beans>
<bean id="injectionService" class="com.imooc.ioc.injection.service.InjectionServiceImpl">
<property name="injectionDAO" ref="injectionDAO"/>
</bean>
<bean id="injectionDAO" class="com.imooc.ioc.injection.dao.InjectionDAOImpl"/>
</beans>


  构造注入:必须有个构造器,构造器的参数是InjectionDAO

<bean id="injectionService" class="com.imooc.ioc.injection.service.InjectionServiceImpl">
<constructor-arg name="injectionDAO" ref="injectionDAO"/>
</bean>


**3-1:Spring Bean装配之Bean的配置项及作用域**

1.Bean配置项

  Id

  Class

  Scope

  Constructor arguments

  Properties

  Autowiring mode

  lazy-initialization mode

  Initialization/destruction method

  Bean的作用域(scope)

  singleton:单例,指一个Bean容器中只存在一份,默认使用

  prototype:每次请求(每次使用)创建新的,destroy方式不生效

  request:每次http请求创建一个实例且仅在当前request内有效

  session:同上,每次http请求创建,当前session内有效

  global session:基于portlet的web中有效(portlet定义了global session),如果是在web中,同session
**3-2:spring Bean装配之Bean的生命周期**

1.生命周期

  定义

  初始化

  使用
  销毁

在网上一个比较好的图片,引用一下



2.初始化

  实现org.springframework.beans.factory.InitializingBean接口,覆盖afterPropertiesSet方法

  配置init-method
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>

  public class Examplebean{
public void init(){}

  } 

3.销毁

  实现org.springframework.beans.factory.DisposableBean接口,覆盖destroy方法

  配置destroy-method
4.配置全局默认初始化.销毁方法

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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" default-init-method="init" default-destory-method="destroy">
</beans>


**3-3.Spring Bean装配之Aware接口**

1.ApplicationContextAware

  BeanNameAware

Java文件

 
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class MoocbeanName implements BeanNameAware,ApplicationContextAware{
private String name;
public void setBeanName(String arg0) {
name=arg0;
System.out.println("MoocbeanName:"+arg0);
}
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
System.out.println("MoocbeanName:"+arg0.getBean(name).hashCode());
}
}


spring-aware.xml

  <bean id="moocbeanName" class="com.imooc.aware.MoocbeanName"/>
测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-aware.xml"})
public class MoocApplicationContextTest {
@Autowired
ApplicationContext ac;
@Test
public void testBeanname(){
System.out.println("testBeanname:"+ac.getBean("moocbeanName").hashCode());
}
}


打印:

  MoocbeanName:moocbeanName

  MoocbeanName:1607305514

  testBeanname:1607305514
**3-4.Spring Bean装配之自动装配(Autowiring)**

  No:不做任何操作

  byname:根据属性名自动装配

  byType:类型,如果没有找到相匹配的bean,则什么事都不发生

  Constructor:与byType方式类似,不同之处在于它应用与构造器参数。如果没有找到,那么就抛出异常

  

  正常的是以“设值注入”和“构造注入”,现在不用写这个,用自动装配

  <beans ..... default-autowire="byName">

  </beans>

**3-5.Spring Bean装配之Resource**

1.针对于资源文件的统一接口

  - UrlResource : URL对应的资源,根据一个URL地址即可构建

  - ClassPathResource : 获取类路径下的资源文件

  - FileSystemResource : 获取文件系统里面的资源

  - ServletContextResource : ServletContext封装的资源,用于访问ServletContext环境下的资源

  - InputStreamResource : 针对于输入流封装的资源

  - ByteArrayResource : 针对于字节数组封装的资源

2.ResourceLoader

  所有Application contexts都包含接口ResourceLoader
  
public interface ResourceLoader{
Resource getResource(String location);
}
Resource template = ctx.getResource("some/resource/path/myTemplate.txt");//依赖于Application context
Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
Resource template = ctx.getResource("file:/some/resource/path/myTemplate.txt");

public class MoocResource implements ApplicationContextAware{
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
this.applicationContext=arg0;
}
public void resource() throws IOException{
//Resource resource = applicationContext.getResource("classpath:config.txt");
//Resource resource = applicationContext.getResource("file:F:\\eclipse-jee-mars-2-win32-x86_64\\eclipse\\workspace\\Spring\\src\\main\\resources\\config.txt");
//Resource resource = applicationContext.getResource("url:http://www.w3school.com.cn/xml/xml_syntax.asp");
Resource resource = applicationContext.getResource("config.txt");//依赖于Application context,也就是classpath
System.out.println("file:"+resource.getFilename());
System.out.println("length:"+resource.contentLength());
}
}


**4-1.Spring Bean装配之Bean的定义及作用域的注解实现**

1.<context:annotation-config/>:仅会查找在同一个AppliationContext中的Bean注解

  @Component,@Repository,@Service,@Controller

  @Required

  @Autowired

  @Qualifier

  @Resource

  

  <context:component-scan>包含<context:annotation-config>,通常在使用前者后,不再使用后者

2.默认情况下,类被自动发现并注册bean的条件是:使用@Component,@Repository,@Service,@Controller注解或者使用@Component的自定义注解

  如:下面例子的XML配置忽略所有的@Repository注解并用“Stub”代替

 
<beans>
<context:component-scan base-package="org.example">
<context:include-filter type="regex" expression=".*Stub.*Repository"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
</beans>


  type包含:annotation,assignable,aspectj,regex,custom

3.还可以使用use-default-filters="false"禁用自动发现与注册

4,定义Bean

 . @Service("myMovieListener")
 . 可以自定义bean的命令策略  

<beans>
<context:component-scan base-package="org.example" name-generator="org.example.MyNameGenerator"/>
</beans>


5,作用域(Scope)

  @Scope("prototype")
  也可以自定义scope策略,实现ScopeMetadataResolver接口并提供一个无参构造器 

<beans>
<context:component-scan base-package="org.example" scope-resolver="org.example.MyScopeResolver"/>
</beans>


6,代理方式

  可以使用scoped-proxy属性指定代理,有三个值可选:no,interfaces,targetClass 

<beans>
<context:component-scan base-package="org.example" scoped-proxy="interfaces"/>
</beans>




**4-2.Spring Bean装配之Autowired注解说明-1**

1.@Required注解试用于bean属性的setter方法。
  受影响的bean(MovieFinder)属性必须在配置时被填充,

public class SimpleListerner{
private MovieFinder m;
@Required
public void setMovieFinder(MovieFinder m){
thism=m;
}
}


2.@Autowired

  可以setter方法

 
private MovieFinder m;
@Autowired
public void setMovieFinder(MovieFinder m){
this.m=m;
}


  可用于构造器或者成员变量
@Autowired
private MovieCatelog movieCatelog;
private CustomerPDao cDao;
@Autowired
public MovieRecommender(CustomerPDao cDao){
this.cDao=cDao;
}


  @Autowired(required=false)

  每个类只能有一个构造器被标记为required=true
**4-3.Spring Bean装配之Autowired注解说明-2**

1.可以使用@Autowired注解那些众所周知的解析依赖性接口,比如:BeanFactory,ApplicationContext context,Enviroment,ResourceLoader,ApplicationEventPublisher,

  @Autowired是由Spring BeanPostProcessor处理的,所以不能在自己的BeanPostProcessor或BeanFacotryPostProcessor类型应用这些注解,这些类型必须通过xml或者spring的@Bean注解

  .可以通过添加注解给需要该类型的数组的字段或方法,以提供ApplicationContext中的所有特定类型的bean

  
private Set<MovieCatelog> m;
@Autowired
public void setMovieCatelogs(Set<MovieCatelog> m){
this.m=m;
}


  .可以用于装配key为String的Map
  .如果希望数组有序,可以让bean实现org.springframework.core.Ordered接口或使用的@Order注解

@Order(2)
@Component
public class BeanImplOne implements BeanInterface {
}
@Order(1)
@Component
public class BeanImplTwo implements BeanInterface {
}
@Component
public class BeanInvoker {
@Autowired
private List<BeanInterface> list;

@Autowired
private Map<String,BeanInterface> map;

public void say(){
if(null != list){
System.out.println("list...");
for(BeanInterface bean : list){
System.out.println(bean.getClass().getName());
}
}else{
System.out.println("List is null!!!");
}
if(null!=map && 0!=map.size()){
System.out.println("map....");
for(Map.Entry<String, BeanInterface> entry:map.entrySet()){
System.out.println(entry.getKey()+"  "+entry.getValue().getClass().getName());
}
}else{
System.out.println("map is null!!!!");
}
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-beanannotation.xml"})
public class BeanInvokerTest {
@Autowired
ApplicationContext ac;
@Test
public void testMultiBean() {
BeanInvoker invoker=(BeanInvoker) ac.getBean("beanInvoker");
invoker.say();
}
}


打印结果:

list...

com.imooc.beanannotation.multibean.BeanImplTwo

com.imooc.beanannotation.multibean.BeanImplOne

map....

beanImplOne  com.imooc.beanannotation.multibean.BeanImplOne

beanImplTwo  com.imooc.beanannotation.multibean.BeanImplTwo

**4-4.Spring Bean装配之Autowired注解说明-3**



@Qualifier

  按类型自动装配可能多个bean实例的情况,可以使用Spring的@Qualifier注解缩小范围(或指定唯一),也可以用于指定单独的构造器参数或方法参数

  1.

public class MovieRe{
@Autowired
@Qualifier("main")
private MovieCatalog movieCatelog;
//...
}

public class MovieRe{
private MovieCatalog movicCatelog;
@Autowired
public void prepare(@Qualifier("main") MovieCatelog movieCatelog){
this.movieCatelog=movieCatelog;
}
//...
}


   2.

   
<beans>
<bean class="example.SimpleMovieCatelog">
<qualifier value="main"/>
</bean>
<bean class="example.SimpleMovieCatelog">
<qualifier name="action"/>
</bean>
</beans>


   如果通过名字进行注解注入,主要使用的不是@Autowired(即使在技术上能够通过@Qualifier指定bean的名字)@Resource

   3.@Autowired适用于fields,constructors,multi-argument methods这些允许在参数级别使用@Qualifier注解缩小范围的情况

     @Resource适用于成员变量,只有一个参数的setter方法,所以在目标是构造器或一个多参数方法时,最好的方式是使用qualifiers

**4-5 spring Bean装配之基于Java的容器注解说明——@Bean**

  .@Bean标识一个用于配置和初始化一个由SpringIoC容器管理的新对象的方法,类似于XML配置文件的<bean/>

  .可以在Spring的@Component注解的类中使用@Bean注解(仅仅是可以)。

  .上一点中,通常使用的是@Configuration

  
@Configuration
public class AppConfig{
@Bean
public MyService myService(){
return new MyServiceImpl();
}
}


  等价于

<beans>
<bean id="myS" class="com.acme.services.MyServiceImpl"/>
</beans>


**4-6 spring Bean装配之基于Java的容器注解说明——@ImportResource和@Value**
@Configuration
@ImportResource("classpath:/com/acme/jdbc.properties");
public class AppConfig{
@Value("${jdbc.url}"
private String url;

@Value("${jdbc.username}")
private String username;

@Value("${jdbc.password}")
private String password;

@Bean
public DataSource dataSource(){
return new DriverManagerDataSource(url,username,password);
}
}


等价于

<beans>
<context:annotation-config/>
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
<!--其作用是加载资源文件-->
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>

</bean>
</beans>


**4-7 spring Bean装配之基于Java的容器注解说明——@Bean和@Scope**

默认@Bean是单例的

@Bean

@Scope(value="session",proxyMode=ScopedProxyMode.TARGET_class)

**4-8 spring Bean装配之基于Java的容器注解说明——基于泛型的自动装配**


@Configuration
public class MyConfiguration{
@Bean
public StringStore stringStore(){
return new StringStore();
}
@Bean
public IntegerStore integerStore(){
return new IntegerStore();
}
}


  

使用1

@Autowired
private Store<String> s1;

@Autowired
private Store<Integer> s2;
  

  使用2

  
@Autowired
private List<Store<Integer>> s;


**4-9. Spring Bean装配之Spring对JSR支持的说明**

  @Resource

  @Named 使用特定名称进行依赖注入,于@Component是等效的

  @Injected

**5-1. Spring AOP基本概念及特点**

  AOP:Aspect Oriented Programming的缩写

  通过预编译和运行期动态代理实现程序功能的统一维护的一种技术。

  预编译

  AspectJ

  运行期动态代理(JDK动态代理,CGLib动态代理)

  SpringAOP JbossAOP

  AOP的几个相关概念

  切面(Aspect):

  连接点(Joinpoint)

  通知(Advice):在特定连接点执行的动作

  切入点(Pointcut)

  引入(Introduction)

  目标对象(Target Object)

  AOP代理(AOP Proxy)

  织入(Weaving)

  Advice的类型

  前置通知(Before advice)

  返回后通知(After returning advice)

  抛出异常后通知(After throwing advice)

  后通知(After(finally) advice)

  环绕通知(Around Advice)

**5-2. 配置切面aspect**

  

<aop:config>

    <aop:aspect id="myAspect" ref="aBean">

      ...

    </aop>

</aop:config>

 
**5-3. 配置切入点Pointcut**

  pointcut

  . execution(public **(..)) 切入点为执行所有public方法时

  . execution(* set*(..)) 切入点为执行所有set开始的方法时

  . execution(* com.xyz.service.AccountService.*(..) 切入点为执行AccountService类中的所有方法时

  . execution(* com.xyz.service..(..)) 切入点为执行com.xyz.service包下的所有方法时

  . execution(* com.xyz.service...(..)) 切入点为执行com.xyz.service包及其子包下的所有方法时

  . within(com.xyz.service.*)(only in Spring AOP)

  . within(com.xyz.service..*(only in Spring AOP) within 用于匹配指定类型内的方法执行

  . this(com.xyz.service.AccountService)(only in Spring AOP) this 用于匹配当前AOP代理对象类型的执行方法。

  . target(com.xyz.service.AccountService)(only in Spring AOP) target用于匹配当前目标对象类型的执行方法

  . args(java.io.Serializable)(only in Spring AOP)

  . @Target(org.springframework.tansaction.annotation.Transactional)(only in Spring AOP)

  . @within(org.springframework.tansaction.annotation.Transactional)(only in Spring AOP)

  . @annotation(org.springframework.tansaction.annotation.Transactional)(only in Spring AOP)

  args用于匹配当前执行的方法传入的参数为指定类型的执行方法。

  pointcut

  . @args(com.xyz.security.Classified)(only in Spring AOP)

  . bean(tradeService)(only in Spring AOP)

  . bean(*Service)(only in Spring AOP)
**5-4. Advice应用(上)**

  

<beans>
<bean id="moocAspect" class="com.imooc.aop.schema.advice.MoocAspect"></bean>
<bean id="aspectBiz" class="com.imooc.aop.schema.advice.biz.AspectBiz"></bean>
<aop:config>
<aop:aspect id="moocAspectAOP" ref="moocAspect">
<aop:pointcut expression="execution(* com.imooc.aop.schema.advice.biz.AspectBiz.*(..))" id="moocPointcut"/>
<aop:before method = "before" pointcut-ref = "moocPointcut"/>
<aop:after-returning method="afterReturning" pointcut-ref = "moocPointcut"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="moocPointcut"/>
<aop:after method="after" pointcut-ref="moocPointcut"/>
<aop:around method="around" pointcut-ref="moocPointcut"/>
<aop:around method="aroundInit" pointcut="execution(* com.imooc.aop.schema.advice.biz.AspectBiz.init(String,int))
and args(bizName,times)"/>
</aop:aspect>
</aop:config>
</beans>


public Object around(ProceedingJoinPoint pjp){
//start stopwatch
Object retVal = pjp.proceed();
//stop stopwatch
return retVal;

}

public Object aroundInit(ProceedingJoinPoint pjj,String bizName,int times) throws Throwable{
System.out.println("MoocAspect aroundInit bizName:"+bizName+",times:"+times);
//Start
Object obj= pjj.proceed();
//Stop
return obj;

}

应用举例,记录日志。当执行action类的时候,会记录日志

package com.company.business.admin.core;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.company.business.admin.core.service.IAdminLogManager;
import com.company.common.bean.core.AdminUser;
import com.company.core.util.DateUtil;
/**
* 此切面主要用于切所有action类的所有方法<br/>
* 只要action执行任何方法就会触发该切面
* @since 2016-12-6 16:50
*/
@Component
@Aspect
public class AdminAspect {
@Autowired
private IAdminLogManager adminLogManager;
private Log log = LogFactory.getLog(AdminAspect.class);
@Pointcut("execution (public * com.company.business.admin.dev.*.action.*Controller.*(..))")
public void serviceExecution(){}

@Before("serviceExecution()")
public void startSomething(JoinPoint jp) {
}
@After("serviceExecution()")
public void endSomething(JoinPoint jp) {
AdminUser currUser = UserContext.getCurrentAdminUser();
String username = "未知";
String realname = "未知";
if (currUser != null) {
username = currUser.getUsername();
realname = currUser.getRealname();
}
try {
String methodname = jp.getSignature().getName();
if (!methodname.toLowerCase().contains("list") && !methodname.toLowerCase().contains("show")) {
adminLogManager.add(new AdminLog(username,
realname, //真实姓名
jp.getTarget().getClass().getName(), //操作人操作的controller类
jp.getSignature().getName(), //操作人操作的controller类的方法名
DateUtil.getDateline()//操作时间
));
}

} catch (Exception e) {
log.error("切面插日志异常:" + e.getMessage() ,e);
}

}
}




**5-6. Introductions应用**
  . schema-defined aspects只支持singleton model

<beans>
<bean id="moocAspect" class="com.imooc.aop.schema.advice.MoocAspect"></bean>
<bean id="aspectBiz" class="com.imooc.aop.schema.advice.biz.AspectBiz"></bean>
<aop:config>
<aop:aspect id="moocAspectAOP" ref="moocAspect">
<aop:declare-parents types-matching="com.imooc.aop.schema.advice.biz.*(+)" implement-interface="com.imooc.aop.schema.advice.Fit" default-impl="com.imooc.aop.schema.advice.FitImpl"/>
</aop:aspect>
</aop:config>
</beans>

Fit.java

package com.imooc.aop.schema.advice;

public interface Fit {

void filter();

}


FitImpl.java

package com.imooc.aop.schema.advice;

public class FitImpl implements Fit {

public void filter() {
System.out.println("FitImpl filter.");
}

}


MoocAspect.java

package com.imooc.aop.schema.advice;

import org.aspectj.lang.ProceedingJoinPoint;

public class MoocAspect {

public void before() {
System.out.println("MoocAspect before.");
}

public void afterReturning() {
System.out.println("MoocAspect afterReturning.");
}

public void afterThrowing() {
System.out.println("MoocAspect afterThrowing.");
}

public void after() {
System.out.println("MoocAspect after.");
}

public Object around(ProceedingJoinPoint pjp) {
Object obj = null;
try {
System.out.println("MoocAspect around 1.");
obj = pjp.proceed();
System.out.println("MoocAspect around 2.");
} catch (Throwable e) {
e.printStackTrace();
}
return obj;
}

public Object aroundInit(ProceedingJoinPoint pjp, String bizName, int times) {
System.out.println(bizName + "   " + times);
Object obj = null;
try {
System.out.println("MoocAspect aroundInit 1.");
obj = pjp.proceed();
System.out.println("MoocAspect aroundInit 2.");
} catch (Throwable e) {
e.printStackTrace();
}
return obj;
}

}


AspectBiz.java

package com.imooc.aop.schema.advice.biz;

public class AspectBiz {

public void biz() {
System.out.println("AspectBiz biz.");
//		throw new RuntimeException();
}

public void init(String bizName, int times) {
System.out.println("AspectBiz init : " + bizName + "   " + times);
}

}


test

package com.imooc.aop.schema.advice.biz;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.imooc.aop.schema.advice.Fit;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-aop-schema-advice2.xml"})
public class AspectBizTest2 {
@Autowired
ApplicationContext ac;

@Test
public void testFit() {
Fit biz=(Fit)ac.getBean("aspectBiz");
biz.filter();
}

}


输出结果

FitImpl filter.


**5-7. Advisors**
<beans>
<aop:config>
<aop:pointcut id="businessService"  expression="execution(* com.xyz.myapp.service..(..))"/>
<aop:advisor pointcut-ref="businessService" advice-ref="tx-advice"/>
</aop:config>
<tx:advice id="tx-advice">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
</beans>


**6-1. Spring AOP API的Pointcut,advice概念及应用**

  . NameMatchMethodPointcut根据方法名字进行匹配

  . 成员变量:mappedNames,匹配的方法名集合

  BeforeAdvice

  ThrowsAdvice

  AfterReturningAdvice

  Interceptor

  MethodInterceptor implements Interceptor

  引入通知(Introduction advice)作为一个特殊的拦截通知,需要IntroductionAdvisor和IntroductionInterceptore仅适用于类,不能和任何切入点一起使用。
**6-2. ProxyFactoryBean及相关内容(上)**

<?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"> <bean id="bizLogicImplTarget" class="com.imooc.aop.api.BizLogicImpl"/>

<bean id="moocBeforeAdvice" class="com.imooc.aop.api.MoocBeforeAdvice"/>
<bean id="moocAfterReturningAdvice" class="com.imooc.aop.api.MoocAfterReturningAdvice"/>
<bean id="moocThrowsAdvice" class="com.imooc.aop.api.MoocThrowsAdvice"/>
<bean id="moocMethodInterceptor" class="com.imooc.aop.api.MoocMethodInterceptor"/>

<bean id="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedNames">
<list>
<value>sa*</value>
</list>
</property>
</bean>

<bean id="defaultAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="moocBeforeAdvice"/>
<property name="pointcut" ref="pointcutBean"/>
</bean>

<!-- <bean id="bizLogicImpl" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref bean="bizLogicImplTarget"/>
</property>
<property name="interceptorNames">
<list>
<value>defaultAdvisor</value>
<value>moocBeforeAdvice</value>
<value>moocAfterReturningAdvice</value>
<value>moocThrowsAdvice</value>
<value>moocMethodInterceptor</value>
</list>
</property>
</bean> -->

<bean id="bizLogicImpl" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>com.imooc.aop.api.BizLogic</value>
</property>
<property name="target">
<!-- <ref bean="bizLogicImplTarget"/> -->
<bean class="com.imooc.aop.api.BizLogicImpl"/>
</property>
<property name="interceptorNames">
<list>
<value>moocBeforeAdvice</value>
<value>moocAfterReturningAdvice</value>
<value>moocThrowsAdvice</value>
<value>moocMethodInterceptor</value>
</list>
</property>
</bean>
</beans>


package com.imooc.aop.api;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class MoocBeforeAdvice implements MethodBeforeAdvice {

public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
System.out.println("MoocBeforeAdvice:"+arg0.getName()+"  "+arg1.getClass().getName());

}

}


package com.imooc.aop.api;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

public class MoocAfterReturningAdvice implements AfterReturningAdvice {

public void afterReturning(Object returnVal, Method method, Object[] arg2, Object target) throws Throwable {
System.out.println("MoocAfterReturningAdvice:"+method.getName()+" "+target.getClass().getName()+" "+returnVal);

}

}


package com.imooc.aop.api;

import java.lang.reflect.Method;

import org.springframework.aop.ThrowsAdvice;

public class MoocThrowsAdvice implements ThrowsAdvice{
public void afterThrowing(Exception ex) throws Throwable{
System.out.println("afterThrowingAdvice afterThrowing 1");
}
public void afterThrowing(Method method,Object[] args,Object target,Exception ex) throws Throwable{
System.out.println("afterThrowingAdvice afterThrowing 2:"+method.getName()+""+target.getClass().getName());
}
}


package com.imooc.aop.api;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MoocMethodInterceptor implements MethodInterceptor {

public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("MoocMethodInterceptor 1:"+invocation.getMethod().getName()+" "+invocation.getStaticPart().getClass().getName());
Object obj= invocation.proceed();
System.out.println("MoocMethodInterceptor 2:"+invocation.getMethod().getName()+" "+invocation.getStaticPart().getClass().getName());
return obj;
}

}


package com.imooc.aop.api;

public interface BizLogic {
String save();
}


package com.imooc.aop.api;

public class BizLogicImpl implements BizLogic{

public String save() {
System.out.println("BizLogicImpl:BizLogicImpl save.");
return "Logic save.";
}

}


测试类

package com.imooc.aop.api;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-aop-api.xml"})

public class BizLogicImplTest {
@Autowired
ApplicationContext ac;
@Test
public void testAA() {
BizLogic logic=(BizLogic) ac.getBean("bizLogicImpl");
logic.save();
}

}


运行结果

MoocBeforeAdvice:save  [Ljava.lang.Object;
MoocMethodInterceptor 1:save java.lang.reflect.Method
BizLogicImpl:BizLogicImpl save.
MoocMethodInterceptor 2:save java.lang.reflect.Method
MoocAfterReturningAdvice:save com.imooc.aop.api.BizLogicImpl Logic save.


**6-3. ProxyFactoryBean及相关内容(下)**

  Proxying classes

  . 前面的例子,如果没有Person接口,这种情况下Spring会使用CGLIB代理,而不是JDK动态代理。

  . CGLIB(Code Generation Library)代理的工作原理是在运行时生产目标类的子类,Spring配置这个生成的子类委托方法调用到原来的目标。

  . 用*做通配,匹配所有拦截器(Interceptor而不是Advice)加入通知链

 

<property name="interceptorNames">
<list>
<value>global*</value>
</list>
</property>


  简化的proxy定义

  抽象属性标记父bean定义为抽象的这样它不能被实例化

  

<beans>
<bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>

<bean id="myService" parent="txProxyTemplate">
<property name="target">
<bean class="org.springframework.samples.MySpecialServiceImpl"/>
</property>
<property name="transactionAttributes"><!--此处可以覆盖txProxyTemplate-->
<props>
<prop key="get*">PROPAGATTION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATTION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
</beans>


**7-1. AspectJ介绍及Ponitcut注解应用**

  Spring中配置@AspectJ

  确保AspectJ的aspectjweaver.jar库包含在应用程序(版本1.6.8或更高版本)的classpath中
@Configuration
@EnableAspectJAutoProxy
public class AppConfig{}


  或者是
<aop:aspectj-autoproxy/>


  aspect

  @AspectJ切面使用@Aspect注解配置,拥有@Aspect的任何bean将被Spring自动识别并应用

  @Aspect注解是不能够通过类路径自动检测发现的,所有需要配合使用@Component注释或者在xml配置bean

  pointcut

  一个切入点通过一个普通的方法定义来提供,并且用@Pointcut注释,方法返回类型必须是void

  

  execution:匹配方法执行的连接点

  within:限制匹配特定类型的连接点

  this

  target

  args

  @target

  @args

  @withiin

  @annotation

  组合pointcut

  切入点表达式可以通过&&,||和!进行组合,也可以通过名字引用切入点表达式。

  如:@Pointcut("anyPublicOperation() && inTrading()")
**7-2. Advice定义及实例**

  @Component

@Aspect

public class MoocAspect{
@Before("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))")
public void before(){}

}

  

//After returning advice

@Aspect

public class AfterReturningExample{
@AfterReturning("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
public void doAccessCheck(){}

}

  或者
 @Aspect

public class AfterReturningExample{
@AfterReturning(pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",returning="retVal")
public void doaccessCheck(Object retVal){}

}

  After throwing advice

  @AfterThrowing

  After(finally)advice

  @After

  Around advice
  @Around,通知方法的第一个参数必须是ProceedingJoinPoint类型

@Aspect

public class AroundExample{
@Around("com.xyz.myapp.SystemArchitecture.businessService()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable{
//start stopwatch
Object retVal = pjp.proceed();
//stop stopwatch
return retVal;
}

}



**7-3. Advice扩展**

  代码1.

  
@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation() && args(account,..)")
public void validateAccount(Account account){}


  代码2.

  
@Pointcut("com.xyz.myapp.SystemArchitecture.dataaccessOperation() && args(acount,..)")
private void accountDataAccessOperation(Account account){}

@Before("accountDataAccessOperation(account)")
public void validateAccount(Account account){}


  代码3.

  @Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.NETHOD)

public @interface Auditable{
AuditCode value();

}

  代码4.

@Before("com.xyz.lib.Pointcuts.anyPublicMethod() && @annotation(auditable)")

public void audit(Auditable auditable){
AuditCode code = auditable.value();
//...

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: