使用註解配置springjava
1.導入 spring-aop-5.0.6.RELEASE.jar包web
2.爲主配置文件引入新的命名空間 xmlns:context="http://www.springframework.org/schema/context"spring
<?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-4.0.xsd"> <!--指定掃描com.david.bean下的全部包全部類中的註解 --> <context:component-scan base-package="com.david.bean"></context:component-scan> </beans>
3.在類中使用註解express
@Component("user") //至關於<bean name="user" class="com.david.bean.User" /> public class User { private String name; private Integer age; private Car car; ... }
註解後來又出現了三種,能夠體現層級關係編程
@Component("user") @Service("user") //service層 @Controller("user") //web層 @Repository("user") //dao層
指定做用範圍框架
@Component("user") //至關於<bean name="user" class="com.david.bean.User" /> @Scope(scopeName = "prototype") //至關於<bean name="user" class="com.david.bean.User" scope="prototype"></bean>
值類型注入oop
public class User { @Value("david") //字段注入 破壞了封裝性 private String name; private Integer age; private Car car; @Value("18") //set方法注入 推薦使用 public void setAge(int age) { this.age = age; } ... }
引用類型(對象)注入測試
@Component("car") public class Car { @Value("奧拓") private String name; @Value("red") private String color; ... }
@Component("user") public class User { @Autowired //自動裝配 對象注入 private Car car; ... }
@autowired 自動裝配的方式 若是匹配到多個類型一致的對象,沒法選擇具體注入哪個對 如:this
<bean name="car2" class="com.david.bean.Car"> <property name="name" value="奧迪"></property> <property name="color" value="black"></property> </bean>
此時須要使用@Qualifier("car2")註解告訴容器具體注入哪一個對象 和@autowired一塊兒使用spa
@Autowired @Qualifier("car2") private Car car;
上面這種要使用兩個註解,還有一個註解@Resource 能夠手動指定注入哪一個對象
@Resource(name="car2") //手動指定 private Car car;
初始化和銷燬
public class User { ... @PostConstruct //至關於init-method 對象建立後調用 public void init(){ System.out.println("init"); } @PreDestroy //銷燬前調用 至關於destory-method public void destory(){ System.out.println("destory"); } ... }
aop:面向切面編程,是對oop面向對象編程的補充和完善。
spring中的aop
spring可以爲容器中管理的對象生成動態代理對象。
spring實現aop的原理
1.動態代理(優先使用)
被代理對象必需要實現接口,才能產生代理對象,若是沒有接口將不能使用動態代理技術
2.cglib代理(沒有接口時)
第三方代理技術,能夠對任何類生成代理對象。代理的原理是對目標對象進行繼承代理
spring AOP 名詞解釋:
1.Joinpoint鏈接點:目標對象中,全部能夠加強的方法。(能夠加強的方法)如:UserServiceImpl implements UserService 中實現的方法 save() delete()
2.Pointcut切入點:目標對象中,已經加強的方法。(已加強的方法)如:已經過代理加強的save() 或delete() 能夠單獨指定某些加強或不加強。
3.Advice通知/加強:須要加強的代碼。(代理對象調用目標方法先後執行的代碼)如://前加強 method.invoke(us,arg) //後加強。
4.Target目標對象:被代理對象。如UserServiceImpl。
5.Weaving織入:將通知織入(應用到)切入點的過程。
6.Proxy代理:將通知織入道目標對象以後,造成代理對象。
因此進行AOP編程的關鍵就是定義切入點和定義加強處理,一旦定義了合適的切入點和加強處理,AOP框架將自動生成AOP代理,即:代理對象的方法=加強處理+被代理對象的方法。
基於spring的aop實現
1.導包 aopalliance.jar aspectjweaver.jar spring aop須要這兩個包的支持 下載地址:
http://www.java2s.com/Code/Jar/a/Downloadaopalliancejar.htm
http://www.java2s.com/Code/Jar/a/Downloadaspectjweaverjar.htm
2.準備目標對象
先定義一個接口
public interface IHelloWorld { void printHelloWorld(); void doPrint(); }
在定義兩個接口實現類
public class HelloWorldImpl1 implements IHelloWorld { public void printHelloWorld() { System.out.println("Enter HelloWorldImpl1.printHelloWorld()"); } public void doPrint() { System.out.println("Enter HelloWorldImpl1.doPrint()"); return ; } } public class HelloWorldImpl2 implements IHelloWorld{ public void printHelloWorld() { System.out.println("Enter HelloWorldImpl2.printHelloWorld()"); } public void doPrint() { System.out.println("Enter HelloWorldImpl2.doPrint()"); return ; } }
3.準備通知
package com.david.bean; import org.aspectj.lang.ProceedingJoinPoint; public class MyAdvice { //前置通知-目標方法調用以前調用 public void before() { System.out.println("前置通知"); } //後置通知-目標方法以後調用,若是異常不會調用 public void afterRuning() { System.out.println("後置通知,出現異常不會調用"); } //環繞通知-在目標方法以前和以後都調用 public void around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("環繞前通知"); Object proceed = pjp.proceed();//調用目標方法 System.out.println("環繞後通知"); } //異常通知-若是出現異常就會被調用 public void afterException(){ System.out.println("出現異常"); } //後置通知-目標方法以後調用,不管異常與否都會調用 public void after() { System.out.println("後置通知,不管異常與否都會調用"); } }
4.配置進行織入,將通知織入目標對象中
新建一個aop.xml
<?xml version="1.0" encoding="UTF-8"?> <!--導入aop命名空間 --> <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" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd"> <!--配置目標對象 --> <bean id="helloWorldImpl1" class="com.david.bean.HelloWorldImpl1" /> <bean id="helloWorldImpl2" class="com.david.bean.HelloWorldImpl2" /> <!--配置通知對象 --> <bean id="myAdvice" class="com.david.bean.MyAdvice" /> <!--配置將通知織入目標對象 --> <aop:config> <!--配置切入點:全部方法都加強 --> <aop:pointcut id="allMethod" expression="execution(* com.david.bean.IHelloWorld.*(..))"></aop:pointcut> <aop:aspect id="advice" ref="myAdvice"> <!--通知方法 --> <aop:before method="before" pointcut-ref="allMethod" /> <aop:after-returning method="afterRuning" pointcut-ref="allMethod"></aop:after-returning> <aop:around method="around" pointcut-ref="allMethod"></aop:around> <aop:after method="after" pointcut-ref="allMethod" /> </aop:aspect> </aop:config> </beans>
5.編寫測試類
public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("aop.xml"); IHelloWorld hw1 = (IHelloWorld)ac.getBean("helloWorldImpl1"); IHelloWorld hw2 = (IHelloWorld)ac.getBean("helloWorldImpl2"); hw1.printHelloWorld(); System.out.println(); hw1.doPrint(); System.out.println(); hw2.printHelloWorld(); System.out.println(); hw2.doPrint(); }
使用spring aop開發 就不須要咱們手寫動態代理代碼了,還封裝了cglib代理。能夠對任何類進行代理加強。
spring的aop註解配置
<?xml version="1.0" encoding="UTF-8"?> <!--導入aop命名空間 --> <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" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd"> <!--配置目標對象 --> <bean id="helloWorldImpl1" class="com.david.bean.HelloWorldImpl1" /> <bean id="helloWorldImpl2" class="com.david.bean.HelloWorldImpl2" /> <!--配置通知對象 --> <bean id="myAdvice" class="com.david.bean.MyAdvice" /> <!--開啓使用註解織入目標對象 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
通知類 使用註解設置
@Aspect //表示該類是一個通知類 public class MyAdvice { @Before("execution(* com.david.bean.IHelloWorld.*(..))") //是一個前置通知並指定切入點 public void before() { System.out.println("前置通知"); } @After("execution(* com.david.bean.IHelloWorld.*(..))") public void after() { System.out.println("後置通知,不管異常與否都會調用"); } @AfterReturning("execution(* com.david.bean.IHelloWorld.*(..))") public void afterRuning() { System.out.println("後置通知,出現異常不會調用"); } @Around("execution(* com.david.bean.IHelloWorld.*(..))") public void around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("環繞前通知"); Object proceed = pjp.proceed();//調用目標方法 System.out.println("環繞後通知"); } }
再次運行 效果同樣的。 抽取切入點
package com.david.bean; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; @Aspect //表示該類是一個通知類 public class MyAdvice { //定義一個切入點規則 @Pointcut("execution(* com.david.bean.IHelloWorld.*(..))") public void pc(){ } @Before("MyAdvice.pc()") public void before() { System.out.println("前置通知"); } @After("MyAdvice.pc()") public void after() { System.out.println("後置通知,不管異常與否都會調用"); } @AfterReturning("MyAdvice.pc()") public void afterRuning() { System.out.println("後置通知,出現異常不會調用"); } @Around("MyAdvice.pc()") public void around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("環繞前通知"); Object proceed = pjp.proceed();//調用目標方法 System.out.println("環繞後通知"); } }